Пример #1
0
 def add_user_to_group(group, user):
     ugm = UsersGroupMember()
     ugm.users_group = group
     ugm.user = user
     Session.add(ugm)
     Session.commit()
     return ugm
Пример #2
0
 def update(self, repo_name):
     """
     PUT /repos/repo_name: 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('repo', repo_name=ID),
     #           method='put')
     # url('repo', repo_name=ID)
     self.__load_defaults()
     repo_model = RepoModel()
     changed_name = repo_name
     _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
                      repo_groups=c.repo_groups_choices)()
     try:
         form_result = _form.to_python(dict(request.POST))
         repo = repo_model.update(repo_name, form_result)
         invalidate_cache('get_repo_cached_%s' % repo_name)
         h.flash(_('Repository %s updated successfully' % repo_name),
                 category='success')
         changed_name = repo.repo_name
         action_logger(self.rhodecode_user, 'admin_updated_repo',
                           changed_name, '', self.sa)
         Session.commit()
     except formencode.Invalid, errors:
         defaults = self.__load_data(repo_name)
         defaults.update(errors.value)
         return htmlfill.render(
             render('admin/repos/repo_edit.html'),
             defaults=defaults,
             errors=errors.error_dict or {},
             prefix_error=False,
             encoding="UTF-8")
Пример #3
0
    def test_propagated_permission_from_users_group_lower_weight(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
        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'])
Пример #4
0
    def revoke_users_group_permission(self, apiuser, repo_name, group_name):
        """
        Revoke permission for users group on given repository

        :param repo_name:
        :param group_name:
        """

        try:
            repo = Repository.get_by_repo_name(repo_name)
            if repo is None:
                raise JSONRPCError('unknown repository %s' % repo)

            user_group = UsersGroup.get_by_group_name(group_name)
            if user_group is None:
                raise JSONRPCError('unknown users group %s' % user_group)

            RepoModel().revoke_users_group_permission(repo=repo_name,
                                                      group_name=group_name)

            Session.commit()
            return dict(
                msg='Revoked perm for group: %s in repo: %s' % (
                    group_name, repo_name
                )
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError(
                'failed to edit permission %(repo)s for %(usersgr)s' % dict(
                    usersgr=group_name, repo=repo_name
                )
            )
Пример #5
0
    def update(self, id):
        """PUT /users/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('update_user', id=ID),
        #           method='put')
        # url('user', id=ID)
        user_model = UserModel()
        c.user = user_model.get(id)

        _form = UserForm(edit=True, old_data={'user_id': id,
                                              'email': c.user.email})()
        form_result = {}
        try:
            form_result = _form.to_python(dict(request.POST))
            user_model.update(id, form_result)
            h.flash(_('User updated successfully'), category='success')
            Session.commit()
        except formencode.Invalid, errors:
            e = errors.error_dict or {}
            perm = Permission.get_by_key('hg.create.repository')
            e.update({'create_repo_perm': user_model.has_perm(id, perm)})
            return htmlfill.render(
                render('admin/users/user_edit.html'),
                defaults=errors.value,
                errors=e,
                prefix_error=False,
                encoding="UTF-8")
Пример #6
0
    def add_user_to_users_group(self, apiuser, group_name, username):
        """"
        Add a user to a users group

        :param apiuser:
        :param group_name:
        :param username:
        """

        try:
            users_group = UsersGroup.get_by_group_name(group_name)
            if not users_group:
                raise JSONRPCError('unknown users group %s' % group_name)

            user = User.get_by_username(username)
            if user is None:
                raise JSONRPCError('unknown user %s' % username)

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

            return dict(
                id=ugm.users_group_member_id if ugm != True else None,
                success=success,
                msg=msg
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError('failed to add users group member')
Пример #7
0
    def grant_user_permission(self, apiuser, repo_name, username, perm):
        """
        Grant permission for user on given repository, or update existing one
        if found

        :param repo_name:
        :param username:
        :param perm:
        """

        try:
            repo = Repository.get_by_repo_name(repo_name)
            if repo is None:
                raise JSONRPCError('unknown repository %s' % repo)

            user = User.get_by_username(username)
            if user is None:
                raise JSONRPCError('unknown user %s' % username)

            RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)

            Session.commit()
            return dict(
                msg='Granted perm: %s for user: %s in repo: %s' % (
                    perm, username, repo_name
                )
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError(
                'failed to edit permission %(repo)s for %(user)s' % dict(
                    user=username, repo=repo_name
                )
            )
Пример #8
0
    def create(self):
        """POST /repos_groups: Create a new item"""
        # url('repos_groups')
        self.__load_defaults()
        repos_group_form = ReposGroupForm(available_groups =
                                          c.repo_groups_choices)()
        try:
            form_result = repos_group_form.to_python(dict(request.POST))
            ReposGroupModel().create(
                    group_name=form_result['group_name'],
                    group_description=form_result['group_description'],
                    parent=form_result['group_parent_id']
            )
            Session.commit()
            h.flash(_('created repos group %s') \
                    % form_result['group_name'], category='success')
            #TODO: in futureaction_logger(, '', '', '', self.sa)
        except formencode.Invalid, errors:

            return htmlfill.render(
                render('admin/repos_groups/repos_groups_add.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #9
0
    def update(self, id):
        """PUT /repos_groups/id: Update an existing item"""
        # Forms posted to this method should contain a hidden field:
        #    <input type="hidden" name="_method" value="PUT" />
        # Or using helpers:
        #    h.form(url('repos_group', id=ID),
        #           method='put')
        # url('repos_group', id=ID)

        self.__load_defaults()
        c.repos_group = RepoGroup.get(id)

        repos_group_form = ReposGroupForm(
            edit=True,
            old_data=c.repos_group.get_dict(),
            available_groups=c.repo_groups_choices
        )()
        try:
            form_result = repos_group_form.to_python(dict(request.POST))
            ReposGroupModel().update(id, form_result)
            Session.commit()
            h.flash(_('updated repos group %s') \
                    % form_result['group_name'], category='success')
            #TODO: in futureaction_logger(, '', '', '', self.sa)
        except formencode.Invalid, errors:

            return htmlfill.render(
                render('admin/repos_groups/repos_groups_edit.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #10
0
    def test_delete(self):
        self.log_user()
        cur_user = self._get_logged_user()

        u1 = UserModel().create_or_update(username='******', password='******',
                                               email='*****@*****.**',
                                               name='u1', lastname='u1')
        u2 = UserModel().create_or_update(username='******', password='******',
                                               email='*****@*****.**',
                                               name='u2', lastname='u2')

        # make notifications
        notification = NotificationModel().create(created_by=cur_user,
                                                  subject=u'test',
                                                  body=u'hi there',
                                                  recipients=[cur_user, u1, u2])
        Session.commit()
        u1 = User.get(u1.user_id)
        u2 = User.get(u2.user_id)

        # check DB
        get_notif = lambda un:[x.notification for x in un]
        self.assertEqual(get_notif(cur_user.notifications), [notification])
        self.assertEqual(get_notif(u1.notifications), [notification])
        self.assertEqual(get_notif(u2.notifications), [notification])
        cur_usr_id = cur_user.user_id


        response = self.app.delete(url('notification',
                                       notification_id=
                                       notification.notification_id))

        cur_user = User.get(cur_usr_id)
        self.assertEqual(cur_user.notifications, [])
Пример #11
0
    def repo_public_journal(self, repo_name):
        """
        Set's this repository to be visible in public journal,
        in other words assing default user to follow this repo

        :param repo_name:
        """

        cur_token = request.POST.get('auth_token')
        token = get_token()
        if cur_token == token:
            try:
                repo_id = Repository.get_by_repo_name(repo_name).repo_id
                user_id = User.get_by_username('default').user_id
                self.scm_model.toggle_following_repo(repo_id, user_id)
                h.flash(_('Updated repository visibility in public journal'),
                        category='success')
                Session.commit()
            except:
                h.flash(_('An error occurred during setting this'
                          ' repository in public journal'),
                        category='error')

        else:
            h.flash(_('Token mismatch'), category='error')
        return redirect(url('edit_repo', repo_name=repo_name))
Пример #12
0
    def my_account_update(self):
        """PUT /_admin/my_account_update: 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('admin_settings_my_account_update'),
        #           method='put')
        # url('admin_settings_my_account_update', id=ID)
        user_model = UserModel()
        uid = self.rhodecode_user.user_id
        _form = UserForm(edit=True,
                         old_data={'user_id': uid,
                                   'email': self.rhodecode_user.email})()
        form_result = {}
        try:
            form_result = _form.to_python(dict(request.POST))
            user_model.update_my_account(uid, form_result)
            h.flash(_('Your account was updated successfully'),
                    category='success')
            Session.commit()
        except formencode.Invalid, errors:
            c.user = User.get(self.rhodecode_user.user_id)
            all_repos = self.sa.query(Repository)\
                .filter(Repository.user_id == c.user.user_id)\
                .order_by(func.lower(Repository.repo_name))\
                .all()
            c.user_repos = ScmModel().get_repos(all_repos)

            return htmlfill.render(
                render('admin/users/user_edit_my_account.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #13
0
    def update(self, repo_name):
        repo_model = RepoModel()
        changed_name = repo_name

        self.__load_defaults()

        _form = RepoSettingsForm(edit=True,
                                 old_data={'repo_name': repo_name},
                                 repo_groups=c.repo_groups_choices)()
        try:
            form_result = _form.to_python(dict(request.POST))

            repo_model.update(repo_name, form_result)
            invalidate_cache('get_repo_cached_%s' % repo_name)
            h.flash(_('Repository %s updated successfully' % repo_name),
                    category='success')
            changed_name = form_result['repo_name_full']
            action_logger(self.rhodecode_user, 'user_updated_repo',
                          changed_name, '', self.sa)
            Session.commit()
        except formencode.Invalid, errors:
            c.repo_info = repo_model.get_by_repo_name(repo_name)
            c.users_array = repo_model.get_users_js()
            errors.value.update({'user': c.repo_info.user.username})
            return htmlfill.render(
                render('settings/repo_settings.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #14
0
    def delete(self, repo_name):
        """DELETE /repos/repo_name: 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('repo_settings_delete', repo_name=ID),
        #           method='delete')
        # url('repo_settings_delete', repo_name=ID)

        repo_model = RepoModel()
        repo = repo_model.get_by_repo_name(repo_name)
        if not repo:
            h.flash(_('%s repository is not mapped to db perhaps'
                      ' it was moved or renamed  from the filesystem'
                      ' please run the application again'
                      ' in order to rescan repositories') % repo_name,
                      category='error')

            return redirect(url('home'))
        try:
            action_logger(self.rhodecode_user, 'user_deleted_repo',
                              repo_name, '', self.sa)
            repo_model.delete(repo)
            invalidate_cache('get_repo_cached_%s' % repo_name)
            h.flash(_('deleted repository %s') % repo_name, category='success')
            Session.commit()
        except Exception:
            log.error(traceback.format_exc())
            h.flash(_('An error occurred during deletion of %s') % repo_name,
                    category='error')

        return redirect(url('home'))
Пример #15
0
    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)
Пример #16
0
    def delete(self, id):
        """DELETE /repos_groups/id: Delete an existing item"""
        # Forms posted to this method should contain a hidden field:
        #    <input type="hidden" name="_method" value="DELETE" />
        # Or using helpers:
        #    h.form(url('repos_group', id=ID),
        #           method='delete')
        # url('repos_group', id=ID)

        gr = RepoGroup.get(id)
        repos = gr.repositories.all()
        if repos:
            h.flash(_('This group contains %s repositores and cannot be '
                      'deleted' % len(repos)),
                    category='error')
            return redirect(url('repos_groups'))

        try:
            ReposGroupModel().delete(id)
            Session.commit()
            h.flash(_('removed repos group %s' % gr.group_name), category='success')
            #TODO: in future action_logger(, '', '', '', self.sa)
        except IntegrityError, e:
            if e.message.find('groups_group_parent_id_fkey') != -1:
                log.error(traceback.format_exc())
                h.flash(_('Cannot delete this group it still contains '
                          'subgroups'),
                        category='warning')
            else:
                log.error(traceback.format_exc())
                h.flash(_('error occurred during deletion of repos '
                          'group %s' % gr.group_name), category='error')
Пример #17
0
    def update_user(self, apiuser, userid, username, password, email,
                    firstname, lastname, active, admin, ldap_dn):
        """
        Updates given user

        :param apiuser:
        :param username:
        :param password:
        :param email:
        :param name:
        :param lastname:
        :param active:
        :param admin:
        :param ldap_dn:
        """
        if not UserModel().get_user(userid):
            raise JSONRPCError("user %s does not exist" % username)

        try:
            usr = UserModel().create_or_update(
                username, password, email, firstname,
                lastname, active, admin, ldap_dn
            )
            Session.commit()
            return dict(
                id=usr.user_id,
                msg='updated user %s' % username
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError('failed to update user %s' % username)
Пример #18
0
    def register(self):
        c.auto_active = False
        for perm in User.get_by_username('default').user_perms:
            if perm.permission.permission_name == 'hg.register.auto_activate':
                c.auto_active = True
                break

        if request.POST:

            register_form = RegisterForm()()
            try:
                form_result = register_form.to_python(dict(request.POST))
                form_result['active'] = c.auto_active
                UserModel().create_registration(form_result)
                h.flash(_('You have successfully registered into rhodecode'),
                            category='success')
                Session.commit()
                return redirect(url('login_home'))

            except formencode.Invalid, errors:
                return htmlfill.render(
                    render('/register.html'),
                    defaults=errors.value,
                    errors=errors.error_dict or {},
                    prefix_error=False,
                    encoding="UTF-8")
Пример #19
0
    def remove_user_from_users_group(self, apiuser, group_name, username):
        """
        Remove user from a group

        :param apiuser
        :param group_name
        :param username
        """

        try:
            users_group = UsersGroup.get_by_group_name(group_name)
            if not users_group:
                raise JSONRPCError('unknown users group %s' % group_name)

            user = User.get_by_username(username)
            if user is None:
                raise JSONRPCError('unknown user %s' % username)

            success = UsersGroupModel().remove_user_from_group(users_group, user)
            msg = 'removed member %s from users group %s' % (username, 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 user from group')
Пример #20
0
    def test_notification_counter(self):
        self._clean_notifications()
        self.assertEqual([], Notification.query().all())
        self.assertEqual([], UserNotification.query().all())

        NotificationModel().create(created_by=self.u1,
                            subject=u'title', body=u'hi there_delete',
                            recipients=[self.u3, self.u1])
        Session.commit()

        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u1), 1)
        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u2), 0)
        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u3), 1)

        notification = NotificationModel().create(created_by=self.u1,
                                           subject=u'title', body=u'hi there3',
                                    recipients=[self.u3, self.u1, self.u2])
        Session.commit()

        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u1), 2)
        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u2), 1)
        self.assertEqual(NotificationModel()
                         .get_unread_cnt_for_user(self.u3), 2)
Пример #21
0
    def toggle_following(self):
        cur_token = request.POST.get('auth_token')
        token = h.get_token()
        if cur_token == token:

            user_id = request.POST.get('follows_user_id')
            if user_id:
                try:
                    self.scm_model.toggle_following_user(user_id,
                                                self.rhodecode_user.user_id)
                    Session.commit()
                    return 'ok'
                except:
                    raise HTTPBadRequest()

            repo_id = request.POST.get('follows_repo_id')
            if repo_id:
                try:
                    self.scm_model.toggle_following_repo(repo_id,
                                                self.rhodecode_user.user_id)
                    Session.commit()
                    return 'ok'
                except:
                    raise HTTPBadRequest()

        log.debug('token mismatch %s vs %s' % (cur_token, token))
        raise HTTPBadRequest()
Пример #22
0
    def tearDown(self):
        perm = Permission.query().all()
        for p in perm:
            UserModel().revoke_perm(self.u1, p)

        UserModel().delete(self.u1)
        Session.commit()
Пример #23
0
    def update_perm(self, id):
        """PUT /users_perm/id: Update an existing item"""
        # url('user_perm', id=ID, method='put')

        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)

            perm = Permission.get_by_key('hg.create.repository')
            user_model.grant_perm(id, perm)
            h.flash(_("Granted 'repository create' 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()
        return redirect(url('edit_user', id=id))
Пример #24
0
    def update(self, id):
        """PUT /permissions/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('permission', id=ID),
        #           method='put')
        # url('permission', id=ID)

        permission_model = PermissionModel()

        _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])()

        try:
            form_result = _form.to_python(dict(request.POST))
            form_result.update({'perm_user_name': id})
            permission_model.update(form_result)
            Session.commit()
            h.flash(_('Default permissions updated successfully'),
                    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(
                render('admin/permissions/permissions.html'),
                defaults=defaults,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #25
0
 def delete_comment(self, repo_name, comment_id):
     co = ChangesetComment.get(comment_id)
     owner = lambda: co.author.user_id == c.rhodecode_user.user_id
     if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
         ChangesetCommentsModel().delete(comment=co)
         Session.commit()
         return True
     else:
         raise HTTPForbidden()
Пример #26
0
    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()
Пример #27
0
    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()
Пример #28
0
    def set_valid(cls, key):
        """
        Mark this cache key as active and currently cached

        :param key:
        """
        inv_obj = Session.query(CacheInvalidation).filter(CacheInvalidation.cache_key == key).scalar()
        inv_obj.cache_active = True
        Session.add(inv_obj)
        Session.commit()
Пример #29
0
    def set_valid(cls, key):
        """
        Mark this cache key as active and currently cached

        :param key:
        """
        inv_obj = cls.get_by_key(key)
        inv_obj.cache_active = True
        Session.add(inv_obj)
        Session.commit()
Пример #30
0
    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)
Пример #31
0
    def create_user(self, apiuser, username, email, password, firstname=None,
                    lastname=None, active=True, admin=False, ldap_dn=None):
        """
        Create new user

        :param apiuser:
        :param username:
        :param password:
        :param email:
        :param name:
        :param lastname:
        :param active:
        :param admin:
        :param ldap_dn:
        """
        if User.get_by_username(username):
            raise JSONRPCError("user %s already exist" % username)

        if User.get_by_email(email, case_insensitive=True):
            raise JSONRPCError("email %s already exist" % email)

        if ldap_dn:
            # generate temporary password if ldap_dn
            password = PasswordGenerator().gen_password(length=8)

        try:
            usr = UserModel().create_or_update(
                username, password, email, firstname,
                lastname, active, admin, ldap_dn
            )
            Session.commit()
            return dict(
                id=usr.user_id,
                msg='created new user %s' % username
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError('failed to create user %s' % username)
Пример #32
0
    def grant_users_group_permission(self, apiuser, repo_name, group_name, perm):
        """
        Grant permission for users group on given repository, or update
        existing one if found

        :param repo_name:
        :param group_name:
        :param perm:
        """

        try:
            repo = Repository.get_by_repo_name(repo_name)
            if repo is None:
                raise JSONRPCError('unknown repository %s' % repo)

            user_group = UsersGroup.get_by_group_name(group_name)
            if user_group is None:
                raise JSONRPCError('unknown users group %s' % user_group)

            RepoModel().grant_users_group_permission(repo=repo_name,
                                                     group_name=group_name,
                                                     perm=perm)

            Session.commit()
            return dict(
                msg='Granted perm: %s for group: %s in repo: %s' % (
                    perm, group_name, repo_name
                )
            )
        except Exception:
            log.error(traceback.format_exc())
            raise JSONRPCError(
                'failed to edit permission %(repo)s for %(usersgr)s' % dict(
                    usersgr=group_name, repo=repo_name
                )
            )
Пример #33
0
    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 = 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
Пример #34
0
    def my_account_update(self):
        """PUT /_admin/my_account_update: 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('admin_settings_my_account_update'),
        #           method='put')
        # url('admin_settings_my_account_update', id=ID)
        user_model = UserModel()
        uid = self.rhodecode_user.user_id
        _form = UserForm(edit=True,
                         old_data={
                             'user_id': uid,
                             'email': self.rhodecode_user.email
                         })()
        form_result = {}
        try:
            form_result = _form.to_python(dict(request.POST))
            user_model.update_my_account(uid, form_result)
            h.flash(_('Your account was updated successfully'),
                    category='success')
            Session.commit()
        except formencode.Invalid, errors:
            c.user = User.get(self.rhodecode_user.user_id)
            all_repos = self.sa.query(Repository)\
                .filter(Repository.user_id == c.user.user_id)\
                .order_by(func.lower(Repository.repo_name))\
                .all()
            c.user_repos = ScmModel().get_repos(all_repos)

            return htmlfill.render(
                render('admin/users/user_edit_my_account.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #35
0
    def create(self):
        """POST /repos_groups: Create a new item"""
        # url('repos_groups')
        self.__load_defaults()
        repos_group_form = ReposGroupForm(
            available_groups=c.repo_groups_choices)()
        try:
            form_result = repos_group_form.to_python(dict(request.POST))
            ReposGroupModel().create(
                group_name=form_result['group_name'],
                group_description=form_result['group_description'],
                parent=form_result['group_parent_id'])
            Session.commit()
            h.flash(_('created repos group %s') \
                    % form_result['group_name'], category='success')
            #TODO: in futureaction_logger(, '', '', '', self.sa)
        except formencode.Invalid, errors:

            return htmlfill.render(
                render('admin/repos_groups/repos_groups_add.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
Пример #36
0
    def test_create_notification(self):
        self.assertEqual([], Notification.query().all())
        self.assertEqual([], UserNotification.query().all())

        usrs = [self.u1, self.u2]
        notification = NotificationModel().create(created_by=self.u1,
                                                  subject=u'subj',
                                                  body=u'hi there',
                                                  recipients=usrs)
        Session.commit()
        u1 = User.get(self.u1)
        u2 = User.get(self.u2)
        u3 = User.get(self.u3)
        notifications = Notification.query().all()
        self.assertEqual(len(notifications), 1)

        unotification = UserNotification.query()\
            .filter(UserNotification.notification == notification).all()

        self.assertEqual(notifications[0].recipients, [u1, u2])
        self.assertEqual(notification.notification_id,
                         notifications[0].notification_id)
        self.assertEqual(len(unotification), len(usrs))
        self.assertEqual([x.user.user_id for x in unotification], usrs)
Пример #37
0
    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)
Пример #38
0
    def show(self, notification_id, format='html'):
        """GET /_admin/notifications/id: Show a specific item"""
        # url('notification', notification_id=ID)
        c.user = self.rhodecode_user
        no = Notification.get(notification_id)

        owner = lambda: (no.notifications_to_users.user.user_id == c.user.
                         user_id)
        if no and (h.HasPermissionAny('hg.admin', 'repository.admin')()
                   or owner):
            unotification = NotificationModel()\
                            .get_user_notification(c.user.user_id, no)

            # if this association to user is not valid, we don't want to show
            # this message
            if unotification:
                if unotification.read is False:
                    unotification.mark_as_read()
                    Session.commit()
                c.notification = no

                return render('admin/notifications/show_notification.html')

        return redirect(url('notifications'))
Пример #39
0
    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')
        # add user to group
        UsersGroupModel().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
        ]
        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)\
            .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'})
Пример #40
0
    def test_create_and_remove(self):
        usr = UserModel().create_or_update(username=u'test_user',
                                           password=u'qweqwe',
                                           email=u'*****@*****.**',
                                           name=u'u1',
                                           lastname=u'u1')
        Session.commit()
        self.assertEqual(User.get_by_username(u'test_user'), usr)

        # make users group
        users_group = UsersGroupModel().create('some_example_group')
        Session.commit()

        UsersGroupModel().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)
        UserModel().delete(usr.user_id)
        Session.commit()

        self.assertEqual(UsersGroupMember.query().all(), [])
Пример #41
0
    def test_move_to_root(self):
        g1 = _make_group('t11')
        Session.commit()
        g2 = _make_group('t22', parent_id=g1.group_id)
        Session.commit()

        self.assertEqual(g2.full_path, 't11/t22')
        self.assertTrue(self.__check_path('t11', 't22'))

        g2 = self.__update_group(g2.group_id, 'g22', parent_id=None)
        Session.commit()

        self.assertEqual(g2.group_name, 'g22')
        # we moved out group from t1 to '' so it's full path should be 'g2'
        self.assertEqual(g2.full_path, 'g22')
        self.assertFalse(self.__check_path('t11', 't22'))
        self.assertTrue(self.__check_path('g22'))
Пример #42
0
    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
        form_data = {
            'repo_name':
            HG_REPO,
            'repo_name_full':
            RepoGroup.url_sep().join([self.g1.group_name, HG_REPO]),
            'repo_type':
            'hg',
            'clone_uri':
            '',
            'repo_group':
            self.g1.group_id,
            'description':
            'desc',
            'private':
            False
        }
        self.test_repo = RepoModel().create(form_data, cur_user=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'
        })
Пример #43
0
 def tearDown(self):
     for n in Notification.query().all():
         inst = Notification.get(n.notification_id)
         Session.delete(inst)
     Session.commit()
Пример #44
0
 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)
Пример #45
0
class DbManage(object):
    def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}):
        self.dbname = dbconf.split('/')[-1]
        self.tests = tests
        self.root = root
        self.dburi = dbconf
        self.log_sql = log_sql
        self.db_exists = False
        self.cli_args = cli_args
        self.init_db()

        force_ask = self.cli_args.get('force_ask')
        if force_ask is not None:
            global ask_ok
            ask_ok = lambda *args, **kwargs: force_ask

    def init_db(self):
        engine = create_engine(self.dburi, echo=self.log_sql)
        init_model(engine)
        self.sa = Session()

    def create_tables(self, override=False):
        """
        Create a auth database
        """

        log.info("Any existing database is going to be destroyed")
        if self.tests:
            destroy = True
        else:
            destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
        if not destroy:
            sys.exit('Nothing tables created')
        if destroy:
            Base.metadata.drop_all()

        checkfirst = not override
        Base.metadata.create_all(checkfirst=checkfirst)
        log.info('Created tables for %s' % self.dbname)

    def set_db_version(self):
        ver = DbMigrateVersion()
        ver.version = __dbversion__
        ver.repository_id = 'rhodecode_db_migrations'
        ver.repository_path = 'versions'
        self.sa.add(ver)
        log.info('db version set to: %s' % __dbversion__)

    def upgrade(self):
        """
        Upgrades given database schema to given revision following
        all needed steps, to perform the upgrade

        """

        from rhodecode.lib.dbmigrate.migrate.versioning import api
        from rhodecode.lib.dbmigrate.migrate.exceptions import \
            DatabaseNotControlledError

        if 'sqlite' in self.dburi:
            print('********************** WARNING **********************\n'
                  'Make sure your version of sqlite is at least 3.7.X.  \n'
                  'Earlier versions are known to fail on some migrations\n'
                  '*****************************************************\n')
        upgrade = ask_ok('You are about to perform database upgrade, make '
                         'sure You backed up your database before. '
                         'Continue ? [y/n]')
        if not upgrade:
            sys.exit('No upgrade performed')

        repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
                             'rhodecode/lib/dbmigrate')
        db_uri = self.dburi

        try:
            curr_version = api.db_version(db_uri, repository_path)
            msg = ('Found current database under version'
                   ' control with version %s' % curr_version)

        except (RuntimeError, DatabaseNotControlledError):
            curr_version = 1
            msg = ('Current database is not under version control. Setting'
                   ' as version %s' % curr_version)
            api.version_control(db_uri, repository_path, curr_version)

        notify(msg)

        if curr_version == __dbversion__:
            sys.exit('This database is already at the newest version')

        # clear cache keys
        log.info("Clearing cache keys now...")
        CacheInvalidation.clear_cache()

        upgrade_steps = range(curr_version + 1, __dbversion__ + 1)
        notify('attempting to do database upgrade from '
               'version %s to version %s' % (curr_version, __dbversion__))

        # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
        _step = None
        for step in upgrade_steps:
            notify('performing upgrade step %s' % step)
            time.sleep(2)

            api.upgrade(db_uri, repository_path, step)
            notify('schema upgrade for step %s completed' % (step, ))

            fixture = 'step_%s' % step
            notify('performing fixture step %s' % fixture)
            getattr(UpgradeSteps(self), fixture)()
            self.sa.commit()
            notify('fixture %s completed' % (fixture, ))
            _step = step

        notify('upgrade to version %s successful' % _step)

    def fix_repo_paths(self):
        """
        Fixes a old rhodecode version path into new one without a '*'
        """

        paths = self.sa.query(RhodeCodeUi)\
                .filter(RhodeCodeUi.ui_key == '/')\
                .scalar()

        paths.ui_value = paths.ui_value.replace('*', '')

        try:
            self.sa.add(paths)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_default_user(self):
        """
        Fixes a old default user with some 'nicer' default values,
        used mostly for anonymous access
        """
        def_user = self.sa.query(User)\
                .filter(User.username == 'default')\
                .one()

        def_user.name = 'Anonymous'
        def_user.lastname = 'User'
        def_user.email = '*****@*****.**'

        try:
            self.sa.add(def_user)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_settings(self):
        """
        Fixes rhodecode settings adds ga_code key for google analytics
        """

        hgsettings3 = RhodeCodeSetting('ga_code', '')

        try:
            self.sa.add(hgsettings3)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def admin_prompt(self, second=False):
        if not self.tests:
            import getpass

            # defaults
            defaults = self.cli_args
            username = defaults.get('username')
            password = defaults.get('password')
            email = defaults.get('email')

            def get_password():
                password = getpass.getpass('Specify admin password '
                                           '(min 6 chars):')
                confirm = getpass.getpass('Confirm password:'******'passwords mismatch')
                    return False
                if len(password) < 6:
                    log.error('password is to short use at least 6 characters')
                    return False

                return password

            if username is None:
                username = raw_input('Specify admin username:'******'Specify admin email:')
            self.create_user(username, password, email, True)
        else:
            log.info('creating admin and regular test users')
            from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
            TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
            TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
            TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
            TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL

            self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
                             TEST_USER_ADMIN_EMAIL, True)

            self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
                             TEST_USER_REGULAR_EMAIL, False)

            self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
                             TEST_USER_REGULAR2_EMAIL, False)

    def create_ui_settings(self):
        """
        Creates ui settings, fills out hooks
        and disables dotencode
        """

        #HOOKS
        hooks1_key = RhodeCodeUi.HOOK_UPDATE
        hooks1_ = self.sa.query(RhodeCodeUi)\
            .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()

        hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
        hooks1.ui_section = 'hooks'
        hooks1.ui_key = hooks1_key
        hooks1.ui_value = 'hg update >&2'
        hooks1.ui_active = False
        self.sa.add(hooks1)

        hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
        hooks2_ = self.sa.query(RhodeCodeUi)\
            .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
        hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
        hooks2.ui_section = 'hooks'
        hooks2.ui_key = hooks2_key
        hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
        self.sa.add(hooks2)

        hooks3 = RhodeCodeUi()
        hooks3.ui_section = 'hooks'
        hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
        hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
        self.sa.add(hooks3)

        hooks4 = RhodeCodeUi()
        hooks4.ui_section = 'hooks'
        hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
        hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
        self.sa.add(hooks4)

        hooks5 = RhodeCodeUi()
        hooks5.ui_section = 'hooks'
        hooks5.ui_key = RhodeCodeUi.HOOK_PULL
        hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
        self.sa.add(hooks5)

        hooks6 = RhodeCodeUi()
        hooks6.ui_section = 'hooks'
        hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
        hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
        self.sa.add(hooks6)

        # enable largefiles
        largefiles = RhodeCodeUi()
        largefiles.ui_section = 'extensions'
        largefiles.ui_key = 'largefiles'
        largefiles.ui_value = ''
        self.sa.add(largefiles)

        # enable hgsubversion disabled by default
        hgsubversion = RhodeCodeUi()
        hgsubversion.ui_section = 'extensions'
        hgsubversion.ui_key = 'hgsubversion'
        hgsubversion.ui_value = ''
        hgsubversion.ui_active = False
        self.sa.add(hgsubversion)

        # enable hggit disabled by default
        hggit = RhodeCodeUi()
        hggit.ui_section = 'extensions'
        hggit.ui_key = 'hggit'
        hggit.ui_value = ''
        hggit.ui_active = False
        self.sa.add(hggit)

    def create_ldap_options(self, skip_existing=False):
        """Creates ldap settings"""

        for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
                     ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
                     ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
                     ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
                     ('ldap_filter', ''), ('ldap_search_scope', ''),
                     ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
                     ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:

            if skip_existing and RhodeCodeSetting.get_by_name(k) is not None:
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v)
            self.sa.add(setting)

    def create_default_options(self, skip_existing=False):
        """Creates default settings"""

        for k, v in [('default_repo_enable_locking', False),
                     ('default_repo_enable_downloads', False),
                     ('default_repo_enable_statistics', False),
                     ('default_repo_private', False),
                     ('default_repo_type', 'hg')]:

            if skip_existing and RhodeCodeSetting.get_by_name(k) is not None:
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v)
            self.sa.add(setting)

    def fixup_groups(self):
        def_usr = User.get_default_user()
        for g in RepoGroup.query().all():
            g.group_name = g.get_new_name(g.name)
            self.sa.add(g)
            # get default perm
            default = UserRepoGroupToPerm.query()\
                .filter(UserRepoGroupToPerm.group == g)\
                .filter(UserRepoGroupToPerm.user == def_usr)\
                .scalar()

            if default is None:
                log.debug('missing default permission for group %s adding' % g)
                perm_obj = ReposGroupModel()._create_default_perms(g)
                self.sa.add(perm_obj)

    def reset_permissions(self, username):
        """
        Resets permissions to default state, usefull when old systems had
        bad permissions, we must clean them up

        :param username:
        """
        default_user = User.get_by_username(username)
        if not default_user:
            return

        u2p = UserToPerm.query()\
            .filter(UserToPerm.user == default_user).all()
        fixed = False
        if len(u2p) != len(Permission.DEFAULT_USER_PERMISSIONS):
            for p in u2p:
                Session().delete(p)
            fixed = True
            self.populate_default_permissions()
        return fixed

    def update_repo_info(self):
        RepoModel.update_repoinfo()

    def config_prompt(self, test_repo_path='', retries=3):
        defaults = self.cli_args
        _path = defaults.get('repos_location')
        if retries == 3:
            log.info('Setting up repositories config')

        if _path is not None:
            path = _path
        elif not self.tests and not test_repo_path:
            path = raw_input(
                'Enter a valid absolute path to store repositories. '
                'All repositories in that path will be added automatically:')
        else:
            path = test_repo_path
        path_ok = True

        # check proper dir
        if not os.path.isdir(path):
            path_ok = False
            log.error('Given path %s is not a valid directory' % (path, ))

        elif not os.path.isabs(path):
            path_ok = False
            log.error('Given path %s is not an absolute path' % (path, ))

        # check if path is at least readable.
        if not os.access(path, os.R_OK):
            path_ok = False
            log.error('Given path %s is not readable' % (path, ))

        # check write access, warn user about non writeable paths
        elif not os.access(path, os.W_OK) and path_ok:
            log.warn('No write permission to given path %s' % (path, ))
            if not ask_ok('Given path %s is not writeable, do you want to '
                          'continue with read only mode ? [y/n]' % (path, )):
                log.error('Canceled by user')
                sys.exit(-1)

        if retries == 0:
            sys.exit('max retries reached')
        if not path_ok:
            retries -= 1
            return self.config_prompt(test_repo_path, retries)

        real_path = os.path.normpath(os.path.realpath(path))

        if real_path != os.path.normpath(path):
            if not ask_ok(('Path looks like a symlink, Rhodecode will store '
                           'given path as %s ? [y/n]') % (real_path, )):
                log.error('Canceled by user')
                sys.exit(-1)

        return real_path

    def create_settings(self, path):

        self.create_ui_settings()

        ui_config = [
            ('web', 'push_ssl', 'false'),
            ('web', 'allow_archive', 'gz zip bz2'),
            ('web', 'allow_push', '*'),
            ('web', 'baseurl', '/'),
            ('paths', '/', path),
            #('phases', 'publish', 'false')
        ]
        for section, key, value in ui_config:
            ui_conf = RhodeCodeUi()
            setattr(ui_conf, 'ui_section', section)
            setattr(ui_conf, 'ui_key', key)
            setattr(ui_conf, 'ui_value', value)
            self.sa.add(ui_conf)

        settings = [('realm', 'RhodeCode authentication', unicode),
                    ('title', 'RhodeCode', unicode), ('ga_code', '', unicode),
                    ('show_public_icon', True, bool),
                    ('show_private_icon', True, bool),
                    ('stylify_metatags', False, bool),
                    ('dashboard_items', 100, int),
                    ('show_version', True, bool)]
        for key, val, type_ in settings:
            sett = RhodeCodeSetting(key, val)
            self.sa.add(sett)

        self.create_ldap_options()
        self.create_default_options()

        log.info('created ui config')

    def create_user(self, username, password, email='', admin=False):
        log.info('creating user %s' % username)
        UserModel().create_or_update(username,
                                     password,
                                     email,
                                     firstname='RhodeCode',
                                     lastname='Admin',
                                     active=True,
                                     admin=admin)

    def create_default_user(self):
        log.info('creating default user')
        # create default user for handling default permissions.
        user = UserModel().create_or_update(username=User.DEFAULT_USER,
                                            password=str(uuid.uuid1())[:20],
                                            email='*****@*****.**',
                                            firstname='Anonymous',
                                            lastname='User')
        # based on configuration options activate/deactive this user which
        # controlls anonymous access
        if self.cli_args.get('public_access') is False:
            log.info('Public access disabled')
            user.active = False
            Session().add(user)
            Session().commit()

    def create_permissions(self):
        """
        Creates all permissions defined in the system
        """
        # module.(access|create|change|delete)_[name]
        # module.(none|read|write|admin)
        log.info('creating permissions')
        PermissionModel(self.sa).create_permissions()

    def populate_default_permissions(self):
        """
        Populate default permissions. It will create only the default
        permissions that are missing, and not alter already defined ones
        """
        log.info('creating default user permissions')
        PermissionModel(
            self.sa).create_default_permissions(user=User.DEFAULT_USER)

    @staticmethod
    def check_waitress():
        """
        Function executed at the end of setup
        """
        if not __py_version__ >= (2, 6):
            notify('Python2.5 detected, please switch '
                   'egg:waitress#main -> egg:Paste#http '
                   'in your .ini file')
Пример #46
0
    def tearDown(self):
        for n in Notification.query().all():
            Session.delete(n)

        Session.commit()
        self.assertEqual(Notification.query().all(), [])
Пример #47
0
    def _clean_notifications(self):
        for n in Notification.query().all():
            Session.delete(n)

        Session.commit()
        self.assertEqual(Notification.query().all(), [])
Пример #48
0
def authenticate(username, password):
    """
    Authentication function used for access control,
    firstly checks for db authentication then if ldap is enabled for ldap
    authentication, also creates ldap user if not in database

    :param username: username
    :param password: password
    """

    user_model = UserModel()
    user = User.get_by_username(username)

    log.debug('Authenticating user using RhodeCode account')
    if user is not None and not user.ldap_dn:
        if user.active:
            if user.username == 'default' and user.active:
                log.info('user %s authenticated correctly as anonymous user' %
                         username)
                return True

            elif user.username == username and check_password(password,
                                                              user.password):
                log.info('user %s authenticated correctly' % username)
                return True
        else:
            log.warning('user %s tried auth but is disabled' % username)

    else:
        log.debug('Regular authentication failed')
        user_obj = User.get_by_username(username, case_insensitive=True)

        if user_obj is not None and not user_obj.ldap_dn:
            log.debug('this user already exists as non ldap')
            return False

        ldap_settings = RhodeCodeSetting.get_ldap_settings()
        #======================================================================
        # FALLBACK TO LDAP AUTH IF ENABLE
        #======================================================================
        if str2bool(ldap_settings.get('ldap_active')):
            log.debug("Authenticating user using ldap")
            kwargs = {
                  'server': ldap_settings.get('ldap_host', ''),
                  'base_dn': ldap_settings.get('ldap_base_dn', ''),
                  'port': ldap_settings.get('ldap_port'),
                  'bind_dn': ldap_settings.get('ldap_dn_user'),
                  'bind_pass': ldap_settings.get('ldap_dn_pass'),
                  'tls_kind': ldap_settings.get('ldap_tls_kind'),
                  'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
                  'ldap_filter': ldap_settings.get('ldap_filter'),
                  'search_scope': ldap_settings.get('ldap_search_scope'),
                  'attr_login': ldap_settings.get('ldap_attr_login'),
                  'ldap_version': 3,
                  }
            log.debug('Checking for ldap authentication')
            try:
                aldap = AuthLdap(**kwargs)
                (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
                                                                password)
                log.debug('Got ldap DN response %s' % user_dn)

                get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
                                                           .get(k), [''])[0]

                user_attrs = {
                 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
                 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
                 'email': get_ldap_attr('ldap_attr_email'),
                }

                # don't store LDAP password since we don't need it. Override
                # with some random generated password
                _password = PasswordGenerator().gen_password(length=8)
                # create this user on the fly if it doesn't exist in rhodecode
                # database
                if user_model.create_ldap(username, _password, user_dn,
                                          user_attrs):
                    log.info('created new ldap user %s' % username)

                Session.commit()
                return True
            except (LdapUsernameError, LdapPasswordError,):
                pass
            except (Exception,):
                log.error(traceback.format_exc())
                pass
    return False
Пример #49
0
class DbManage(object):
    def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}):
        self.dbname = dbconf.split('/')[-1]
        self.tests = tests
        self.root = root
        self.dburi = dbconf
        self.log_sql = log_sql
        self.db_exists = False
        self.cli_args = cli_args
        self.init_db()

        force_ask = self.cli_args.get('force_ask')
        if force_ask is not None:
            global ask_ok
            ask_ok = lambda *args, **kwargs: force_ask

    def init_db(self):
        engine = create_engine(self.dburi, echo=self.log_sql)
        init_model(engine)
        self.sa = Session()

    def create_tables(self, override=False):
        """
        Create a auth database
        """

        log.info("Any existing database is going to be destroyed")
        if self.tests:
            destroy = True
        else:
            destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
        if not destroy:
            sys.exit('Nothing done')
        if destroy:
            Base.metadata.drop_all()

        checkfirst = not override
        Base.metadata.create_all(checkfirst=checkfirst)
        log.info('Created tables for %s' % self.dbname)

    def set_db_version(self):
        ver = DbMigrateVersion()
        ver.version = __dbversion__
        ver.repository_id = 'rhodecode_db_migrations'
        ver.repository_path = 'versions'
        self.sa.add(ver)
        log.info('db version set to: %s' % __dbversion__)

    def upgrade(self):
        """
        Upgrades given database schema to given revision following
        all needed steps, to perform the upgrade

        """

        from rhodecode.lib.dbmigrate.migrate.versioning import api
        from rhodecode.lib.dbmigrate.migrate.exceptions import \
            DatabaseNotControlledError

        if 'sqlite' in self.dburi:
            print (
               '********************** WARNING **********************\n'
               'Make sure your version of sqlite is at least 3.7.X.  \n'
               'Earlier versions are known to fail on some migrations\n'
               '*****************************************************\n'
            )
        upgrade = ask_ok('You are about to perform database upgrade, make '
                         'sure You backed up your database before. '
                         'Continue ? [y/n]')
        if not upgrade:
            sys.exit('Nothing done')

        repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
                             'rhodecode/lib/dbmigrate')
        db_uri = self.dburi

        try:
            curr_version = api.db_version(db_uri, repository_path)
            msg = ('Found current database under version'
                 ' control with version %s' % curr_version)

        except (RuntimeError, DatabaseNotControlledError):
            curr_version = 1
            msg = ('Current database is not under version control. Setting'
                   ' as version %s' % curr_version)
            api.version_control(db_uri, repository_path, curr_version)

        notify(msg)

        if curr_version == __dbversion__:
            sys.exit('This database is already at the newest version')

        #======================================================================
        # UPGRADE STEPS
        #======================================================================

        class UpgradeSteps(object):
            """
            Those steps follow schema versions so for example schema
            for example schema with seq 002 == step_2 and so on.
            """

            def __init__(self, klass):
                self.klass = klass

            def step_0(self):
                # step 0 is the schema upgrade, and than follow proper upgrades
                notify('attempting to do database upgrade from '
                       'version %s to version %s' %(curr_version, __dbversion__))
                api.upgrade(db_uri, repository_path, __dbversion__)
                notify('Schema upgrade completed')

            def step_1(self):
                pass

            def step_2(self):
                notify('Patching repo paths for newer version of RhodeCode')
                self.klass.fix_repo_paths()

                notify('Patching default user of RhodeCode')
                self.klass.fix_default_user()

                log.info('Changing ui settings')
                self.klass.create_ui_settings()

            def step_3(self):
                notify('Adding additional settings into RhodeCode db')
                self.klass.fix_settings()
                notify('Adding ldap defaults')
                self.klass.create_ldap_options(skip_existing=True)

            def step_4(self):
                notify('create permissions and fix groups')
                self.klass.create_permissions()
                self.klass.fixup_groups()

            def step_5(self):
                pass

            def step_6(self):

                notify('re-checking permissions')
                self.klass.create_permissions()

                notify('installing new UI options')
                sett4 = RhodeCodeSetting('show_public_icon', True)
                Session().add(sett4)
                sett5 = RhodeCodeSetting('show_private_icon', True)
                Session().add(sett5)
                sett6 = RhodeCodeSetting('stylify_metatags', False)
                Session().add(sett6)

                notify('fixing old PULL hook')
                _pull = RhodeCodeUi.get_by_key('preoutgoing.pull_logger')
                if _pull:
                    _pull.ui_key = RhodeCodeUi.HOOK_PULL
                    Session().add(_pull)

                notify('fixing old PUSH hook')
                _push = RhodeCodeUi.get_by_key('pretxnchangegroup.push_logger')
                if _push:
                    _push.ui_key = RhodeCodeUi.HOOK_PUSH
                    Session().add(_push)

                notify('installing new pre-push hook')
                hooks4 = RhodeCodeUi()
                hooks4.ui_section = 'hooks'
                hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
                hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
                Session().add(hooks4)

                notify('installing new pre-pull hook')
                hooks6 = RhodeCodeUi()
                hooks6.ui_section = 'hooks'
                hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
                hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
                Session().add(hooks6)

                notify('installing hgsubversion option')
                # enable hgsubversion disabled by default
                hgsubversion = RhodeCodeUi()
                hgsubversion.ui_section = 'extensions'
                hgsubversion.ui_key = 'hgsubversion'
                hgsubversion.ui_value = ''
                hgsubversion.ui_active = False
                Session().add(hgsubversion)

                notify('installing hg git option')
                # enable hggit disabled by default
                hggit = RhodeCodeUi()
                hggit.ui_section = 'extensions'
                hggit.ui_key = 'hggit'
                hggit.ui_value = ''
                hggit.ui_active = False
                Session().add(hggit)

                notify('re-check default permissions')
                default_user = User.get_by_username(User.DEFAULT_USER)
                perm = Permission.get_by_key('hg.fork.repository')
                reg_perm = UserToPerm()
                reg_perm.user = default_user
                reg_perm.permission = perm
                Session().add(reg_perm)

            def step_7(self):
                perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
                Session().commit()
                if perm_fixes:
                    notify('There was an inconsistent state of permissions '
                           'detected for default user. Permissions are now '
                           'reset to the default value for default user. '
                           'Please validate and check default permissions '
                           'in admin panel')

            def step_8(self):
                self.klass.populate_default_permissions()
                self.klass.create_default_options(skip_existing=True)
                Session().commit()

            def step_9(self):
                perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER)
                Session().commit()
                if perm_fixes:
                    notify('There was an inconsistent state of permissions '
                           'detected for default user. Permissions are now '
                           'reset to the default value for default user. '
                           'Please validate and check default permissions '
                           'in admin panel')

            def step_10(self):
                pass

            def step_11(self):
                self.klass.update_repo_info()

        upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)

        # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
        _step = None
        for step in upgrade_steps:
            notify('performing upgrade step %s' % step)
            getattr(UpgradeSteps(self), 'step_%s' % step)()
            self.sa.commit()
            _step = step

        notify('upgrade to version %s successful' % _step)

    def fix_repo_paths(self):
        """
        Fixes a old rhodecode version path into new one without a '*'
        """

        paths = self.sa.query(RhodeCodeUi)\
                .filter(RhodeCodeUi.ui_key == '/')\
                .scalar()

        paths.ui_value = paths.ui_value.replace('*', '')

        try:
            self.sa.add(paths)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_default_user(self):
        """
        Fixes a old default user with some 'nicer' default values,
        used mostly for anonymous access
        """
        def_user = self.sa.query(User)\
                .filter(User.username == 'default')\
                .one()

        def_user.name = 'Anonymous'
        def_user.lastname = 'User'
        def_user.email = '*****@*****.**'

        try:
            self.sa.add(def_user)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_settings(self):
        """
        Fixes rhodecode settings adds ga_code key for google analytics
        """

        hgsettings3 = RhodeCodeSetting('ga_code', '')

        try:
            self.sa.add(hgsettings3)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def admin_prompt(self, second=False):
        if not self.tests:
            import getpass

            # defaults
            defaults = self.cli_args
            username = defaults.get('username')
            password = defaults.get('password')
            email = defaults.get('email')

            def get_password():
                password = getpass.getpass('Specify admin password '
                                           '(min 6 chars):')
                confirm = getpass.getpass('Confirm password:'******'passwords mismatch')
                    return False
                if len(password) < 6:
                    log.error('password is to short use at least 6 characters')
                    return False

                return password
            if username is None:
                username = raw_input('Specify admin username:'******'Specify admin email:')
            self.create_user(username, password, email, True)
        else:
            log.info('creating admin and regular test users')
            from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
            TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
            TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
            TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
            TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL

            self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
                             TEST_USER_ADMIN_EMAIL, True)

            self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
                             TEST_USER_REGULAR_EMAIL, False)

            self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
                             TEST_USER_REGULAR2_EMAIL, False)

    def create_ui_settings(self):
        """
        Creates ui settings, fills out hooks
        and disables dotencode
        """

        #HOOKS
        hooks1_key = RhodeCodeUi.HOOK_UPDATE
        hooks1_ = self.sa.query(RhodeCodeUi)\
            .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()

        hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
        hooks1.ui_section = 'hooks'
        hooks1.ui_key = hooks1_key
        hooks1.ui_value = 'hg update >&2'
        hooks1.ui_active = False
        self.sa.add(hooks1)

        hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE
        hooks2_ = self.sa.query(RhodeCodeUi)\
            .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
        hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
        hooks2.ui_section = 'hooks'
        hooks2.ui_key = hooks2_key
        hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
        self.sa.add(hooks2)

        hooks3 = RhodeCodeUi()
        hooks3.ui_section = 'hooks'
        hooks3.ui_key = RhodeCodeUi.HOOK_PUSH
        hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
        self.sa.add(hooks3)

        hooks4 = RhodeCodeUi()
        hooks4.ui_section = 'hooks'
        hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH
        hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push'
        self.sa.add(hooks4)

        hooks5 = RhodeCodeUi()
        hooks5.ui_section = 'hooks'
        hooks5.ui_key = RhodeCodeUi.HOOK_PULL
        hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
        self.sa.add(hooks5)

        hooks6 = RhodeCodeUi()
        hooks6.ui_section = 'hooks'
        hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL
        hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull'
        self.sa.add(hooks6)

        # enable largefiles
        largefiles = RhodeCodeUi()
        largefiles.ui_section = 'extensions'
        largefiles.ui_key = 'largefiles'
        largefiles.ui_value = ''
        self.sa.add(largefiles)

        # enable hgsubversion disabled by default
        hgsubversion = RhodeCodeUi()
        hgsubversion.ui_section = 'extensions'
        hgsubversion.ui_key = 'hgsubversion'
        hgsubversion.ui_value = ''
        hgsubversion.ui_active = False
        self.sa.add(hgsubversion)

        # enable hggit disabled by default
        hggit = RhodeCodeUi()
        hggit.ui_section = 'extensions'
        hggit.ui_key = 'hggit'
        hggit.ui_value = ''
        hggit.ui_active = False
        self.sa.add(hggit)

    def create_ldap_options(self, skip_existing=False):
        """Creates ldap settings"""

        for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
                    ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
                    ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
                    ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
                    ('ldap_filter', ''), ('ldap_search_scope', ''),
                    ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
                    ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:

            if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v)
            self.sa.add(setting)

    def create_default_options(self, skip_existing=False):
        """Creates default settings"""

        for k, v in [
            ('default_repo_enable_locking',  False),
            ('default_repo_enable_downloads', False),
            ('default_repo_enable_statistics', False),
            ('default_repo_private', False),
            ('default_repo_type', 'hg')]:

            if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v)
            self.sa.add(setting)

    def fixup_groups(self):
        def_usr = User.get_by_username('default')
        for g in RepoGroup.query().all():
            g.group_name = g.get_new_name(g.name)
            self.sa.add(g)
            # get default perm
            default = UserRepoGroupToPerm.query()\
                .filter(UserRepoGroupToPerm.group == g)\
                .filter(UserRepoGroupToPerm.user == def_usr)\
                .scalar()

            if default is None:
                log.debug('missing default permission for group %s adding' % g)
                ReposGroupModel()._create_default_perms(g)

    def reset_permissions(self, username):
        """
        Resets permissions to default state, usefull when old systems had
        bad permissions, we must clean them up

        :param username:
        :type username:
        """
        default_user = User.get_by_username(username)
        if not default_user:
            return

        u2p = UserToPerm.query()\
            .filter(UserToPerm.user == default_user).all()
        fixed = False
        if len(u2p) != len(User.DEFAULT_PERMISSIONS):
            for p in u2p:
                Session().delete(p)
            fixed = True
            self.populate_default_permissions()
        return fixed

    def update_repo_info(self):
        RepoModel.update_repoinfo()

    def config_prompt(self, test_repo_path='', retries=3):
        defaults = self.cli_args
        _path = defaults.get('repos_location')
        if retries == 3:
            log.info('Setting up repositories config')

        if _path is not None:
            path = _path
        elif not self.tests and not test_repo_path:
            path = raw_input(
                 'Enter a valid absolute path to store repositories. '
                 'All repositories in that path will be added automatically:'
            )
        else:
            path = test_repo_path
        path_ok = True

        # check proper dir
        if not os.path.isdir(path):
            path_ok = False
            log.error('Given path %s is not a valid directory' % path)

        elif not os.path.isabs(path):
            path_ok = False
            log.error('Given path %s is not an absolute path' % path)

        # check write access
        elif not os.access(path, os.W_OK) and path_ok:
            path_ok = False
            log.error('No write permission to given path %s' % path)

        if retries == 0:
            sys.exit('max retries reached')
        if not path_ok:
            retries -= 1
            return self.config_prompt(test_repo_path, retries)

        real_path = os.path.normpath(os.path.realpath(path))

        if real_path != os.path.normpath(path):
            if not ask_ok(('Path looks like a symlink, Rhodecode will store '
                           'given path as %s ? [y/n]') % (real_path)):
                log.error('Canceled by user')
                sys.exit(-1)

        return real_path

    def create_settings(self, path):

        self.create_ui_settings()

        #HG UI OPTIONS
        web1 = RhodeCodeUi()
        web1.ui_section = 'web'
        web1.ui_key = 'push_ssl'
        web1.ui_value = 'false'

        web2 = RhodeCodeUi()
        web2.ui_section = 'web'
        web2.ui_key = 'allow_archive'
        web2.ui_value = 'gz zip bz2'

        web3 = RhodeCodeUi()
        web3.ui_section = 'web'
        web3.ui_key = 'allow_push'
        web3.ui_value = '*'

        web4 = RhodeCodeUi()
        web4.ui_section = 'web'
        web4.ui_key = 'baseurl'
        web4.ui_value = '/'

        paths = RhodeCodeUi()
        paths.ui_section = 'paths'
        paths.ui_key = '/'
        paths.ui_value = path

        phases = RhodeCodeUi()
        phases.ui_section = 'phases'
        phases.ui_key = 'publish'
        phases.ui_value = False

        sett1 = RhodeCodeSetting('realm', 'RhodeCode authentication')
        sett2 = RhodeCodeSetting('title', 'RhodeCode')
        sett3 = RhodeCodeSetting('ga_code', '')

        sett4 = RhodeCodeSetting('show_public_icon', True)
        sett5 = RhodeCodeSetting('show_private_icon', True)
        sett6 = RhodeCodeSetting('stylify_metatags', False)

        self.sa.add(web1)
        self.sa.add(web2)
        self.sa.add(web3)
        self.sa.add(web4)
        self.sa.add(paths)
        self.sa.add(sett1)
        self.sa.add(sett2)
        self.sa.add(sett3)
        self.sa.add(sett4)
        self.sa.add(sett5)
        self.sa.add(sett6)

        self.create_ldap_options()
        self.create_default_options()

        log.info('created ui config')

    def create_user(self, username, password, email='', admin=False):
        log.info('creating user %s' % username)
        UserModel().create_or_update(username, password, email,
                                     firstname='RhodeCode', lastname='Admin',
                                     active=True, admin=admin)

    def create_default_user(self):
        log.info('creating default user')
        # create default user for handling default permissions.
        UserModel().create_or_update(username='******',
                              password=str(uuid.uuid1())[:8],
                              email='*****@*****.**',
                              firstname='Anonymous', lastname='User')

    def create_permissions(self):
        # module.(access|create|change|delete)_[name]
        # module.(none|read|write|admin)

        for p in Permission.PERMS:
            if not Permission.get_by_key(p[0]):
                new_perm = Permission()
                new_perm.permission_name = p[0]
                new_perm.permission_longname = p[0]
                self.sa.add(new_perm)

    def populate_default_permissions(self):
        log.info('creating default user permissions')

        default_user = User.get_by_username('default')

        for def_perm in User.DEFAULT_PERMISSIONS:

            perm = self.sa.query(Permission)\
             .filter(Permission.permission_name == def_perm)\
             .scalar()
            if not perm:
                raise Exception(
                  'CRITICAL: permission %s not found inside database !!'
                  % def_perm
                )
            if not UserToPerm.query()\
                .filter(UserToPerm.permission == perm)\
                .filter(UserToPerm.user == default_user).scalar():
                reg_perm = UserToPerm()
                reg_perm.user = default_user
                reg_perm.permission = perm
                self.sa.add(reg_perm)

    @staticmethod
    def check_waitress():
        """
        Function executed at the end of setup
        """
        if not __py_version__ >= (2, 6):
            notify('Python2.5 detected, please switch '
                   'egg:waitress#main -> egg:Paste#http '
                   'in your .ini file')
Пример #50
0
class DbManage(object):

    def __init__(self, log_sql, dbconf, root, tests=False,
                 SESSION=None, cli_args={}):
        self.dbname = dbconf.split('/')[-1]
        self.tests = tests
        self.root = root
        self.dburi = dbconf
        self.log_sql = log_sql
        self.db_exists = False
        self.cli_args = cli_args
        self.init_db(SESSION=SESSION)
        self.ask_ok = self.get_ask_ok_func(self.cli_args.get('force_ask'))

    def get_ask_ok_func(self, param):
        if param not in [None]:
            # return a function lambda that has a default set to param
            return lambda *args, **kwargs: param
        else:
            from rhodecode.lib.utils import ask_ok
            return ask_ok

    def init_db(self, SESSION=None):
        if SESSION:
            self.sa = SESSION
        else:
            # init new sessions
            engine = create_engine(self.dburi, echo=self.log_sql)
            init_model(engine)
            self.sa = Session()

    def create_tables(self, override=False):
        """
        Create a auth database
        """

        log.info("Existing database with the same name is going to be destroyed.")
        log.info("Setup command will run DROP ALL command on that database.")
        if self.tests:
            destroy = True
        else:
            destroy = self.ask_ok('Are you sure that you want to destroy the old database? [y/n]')
        if not destroy:
            log.info('Nothing done.')
            sys.exit(0)
        if destroy:
            Base.metadata.drop_all()

        checkfirst = not override
        Base.metadata.create_all(checkfirst=checkfirst)
        log.info('Created tables for %s' % self.dbname)

    def set_db_version(self):
        ver = DbMigrateVersion()
        ver.version = __dbversion__
        ver.repository_id = 'rhodecode_db_migrations'
        ver.repository_path = 'versions'
        self.sa.add(ver)
        log.info('db version set to: %s' % __dbversion__)

    def run_pre_migration_tasks(self):
        """
        Run various tasks before actually doing migrations
        """
        # delete cache keys on each upgrade
        total = CacheKey.query().count()
        log.info("Deleting (%s) cache keys now...", total)
        CacheKey.delete_all_cache()

    def upgrade(self):
        """
        Upgrades given database schema to given revision following
        all needed steps, to perform the upgrade

        """

        from rhodecode.lib.dbmigrate.migrate.versioning import api
        from rhodecode.lib.dbmigrate.migrate.exceptions import \
            DatabaseNotControlledError

        if 'sqlite' in self.dburi:
            print (
               '********************** WARNING **********************\n'
               'Make sure your version of sqlite is at least 3.7.X.  \n'
               'Earlier versions are known to fail on some migrations\n'
               '*****************************************************\n')

        upgrade = self.ask_ok(
            'You are about to perform a database upgrade. Make '
            'sure you have backed up your database. '
            'Continue ? [y/n]')
        if not upgrade:
            log.info('No upgrade performed')
            sys.exit(0)

        repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
                             'rhodecode/lib/dbmigrate')
        db_uri = self.dburi

        try:
            curr_version = api.db_version(db_uri, repository_path)
            msg = ('Found current database under version '
                   'control with version %s' % curr_version)

        except (RuntimeError, DatabaseNotControlledError):
            curr_version = 1
            msg = ('Current database is not under version control. Setting '
                   'as version %s' % curr_version)
            api.version_control(db_uri, repository_path, curr_version)

        notify(msg)

        self.run_pre_migration_tasks()

        if curr_version == __dbversion__:
            log.info('This database is already at the newest version')
            sys.exit(0)

        upgrade_steps = range(curr_version + 1, __dbversion__ + 1)
        notify('attempting to upgrade database from '
               'version %s to version %s' % (curr_version, __dbversion__))

        # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
        _step = None
        for step in upgrade_steps:
            notify('performing upgrade step %s' % step)
            time.sleep(0.5)

            api.upgrade(db_uri, repository_path, step)
            self.sa.rollback()
            notify('schema upgrade for step %s completed' % (step,))

            _step = step

        notify('upgrade to version %s successful' % _step)

    def fix_repo_paths(self):
        """
        Fixes an old RhodeCode version path into new one without a '*'
        """

        paths = self.sa.query(RhodeCodeUi)\
                .filter(RhodeCodeUi.ui_key == '/')\
                .scalar()

        paths.ui_value = paths.ui_value.replace('*', '')

        try:
            self.sa.add(paths)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_default_user(self):
        """
        Fixes an old default user with some 'nicer' default values,
        used mostly for anonymous access
        """
        def_user = self.sa.query(User)\
                .filter(User.username == User.DEFAULT_USER)\
                .one()

        def_user.name = 'Anonymous'
        def_user.lastname = 'User'
        def_user.email = User.DEFAULT_USER_EMAIL

        try:
            self.sa.add(def_user)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def fix_settings(self):
        """
        Fixes rhodecode settings and adds ga_code key for google analytics
        """

        hgsettings3 = RhodeCodeSetting('ga_code', '')

        try:
            self.sa.add(hgsettings3)
            self.sa.commit()
        except Exception:
            self.sa.rollback()
            raise

    def create_admin_and_prompt(self):

        # defaults
        defaults = self.cli_args
        username = defaults.get('username')
        password = defaults.get('password')
        email = defaults.get('email')

        if username is None:
            username = raw_input('Specify admin username:'******'Specify admin email:')
        api_key = self.cli_args.get('api_key')
        self.create_user(username, password, email, True,
                         strict_creation_check=False,
                         api_key=api_key)

    def _get_admin_password(self):
        password = getpass.getpass('Specify admin password '
                                   '(min 6 chars):')
        confirm = getpass.getpass('Confirm password:'******'passwords mismatch')
            return False
        if len(password) < 6:
            log.error('password is too short - use at least 6 characters')
            return False

        return password

    def create_test_admin_and_users(self):
        log.info('creating admin and regular test users')
        from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
            TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
            TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
            TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
            TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL

        self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
                         TEST_USER_ADMIN_EMAIL, True)

        self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
                         TEST_USER_REGULAR_EMAIL, False)

        self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
                         TEST_USER_REGULAR2_EMAIL, False)

    def create_ui_settings(self, repo_store_path):
        """
        Creates ui settings, fills out hooks
        and disables dotencode
        """
        settings_model = SettingsModel(sa=self.sa)

        # Build HOOKS
        hooks = [
            (RhodeCodeUi.HOOK_REPO_SIZE, 'python:vcsserver.hooks.repo_size'),

            # HG
            (RhodeCodeUi.HOOK_PRE_PULL, 'python:vcsserver.hooks.pre_pull'),
            (RhodeCodeUi.HOOK_PULL, 'python:vcsserver.hooks.log_pull_action'),
            (RhodeCodeUi.HOOK_PRE_PUSH, 'python:vcsserver.hooks.pre_push'),
            (RhodeCodeUi.HOOK_PUSH, 'python:vcsserver.hooks.log_push_action'),

        ]

        for key, value in hooks:
            hook_obj = settings_model.get_ui_by_key(key)
            hooks2 = hook_obj if hook_obj else RhodeCodeUi()
            hooks2.ui_section = 'hooks'
            hooks2.ui_key = key
            hooks2.ui_value = value
            self.sa.add(hooks2)

        # enable largefiles
        largefiles = RhodeCodeUi()
        largefiles.ui_section = 'extensions'
        largefiles.ui_key = 'largefiles'
        largefiles.ui_value = ''
        self.sa.add(largefiles)

        # set default largefiles cache dir, defaults to
        # /repo location/.cache/largefiles
        largefiles = RhodeCodeUi()
        largefiles.ui_section = 'largefiles'
        largefiles.ui_key = 'usercache'
        largefiles.ui_value = os.path.join(repo_store_path, '.cache',
                                           'largefiles')
        self.sa.add(largefiles)

        # enable hgsubversion disabled by default
        hgsubversion = RhodeCodeUi()
        hgsubversion.ui_section = 'extensions'
        hgsubversion.ui_key = 'hgsubversion'
        hgsubversion.ui_value = ''
        hgsubversion.ui_active = False
        self.sa.add(hgsubversion)

        # enable hggit disabled by default
        hggit = RhodeCodeUi()
        hggit.ui_section = 'extensions'
        hggit.ui_key = 'hggit'
        hggit.ui_value = ''
        hggit.ui_active = False
        self.sa.add(hggit)

        # set svn branch defaults
        branches = ["/branches/*", "/trunk"]
        tags = ["/tags/*"]

        for branch in branches:
            settings_model.create_ui_section_value(
                RhodeCodeUi.SVN_BRANCH_ID, branch)

        for tag in tags:
            settings_model.create_ui_section_value(RhodeCodeUi.SVN_TAG_ID, tag)

    def create_auth_plugin_options(self, skip_existing=False):
        """
        Create default auth plugin settings, and make it active

        :param skip_existing:
        """

        for k, v, t in [('auth_plugins', 'egg:rhodecode-enterprise-ce#rhodecode', 'list'),
                        ('auth_rhodecode_enabled', 'True', 'bool')]:
            if (skip_existing and
                    SettingsModel().get_setting_by_name(k) is not None):
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v, t)
            self.sa.add(setting)

    def create_default_options(self, skip_existing=False):
        """Creates default settings"""

        for k, v, t in [
            ('default_repo_enable_locking',  False, 'bool'),
            ('default_repo_enable_downloads', False, 'bool'),
            ('default_repo_enable_statistics', False, 'bool'),
            ('default_repo_private', False, 'bool'),
            ('default_repo_type', 'hg', 'unicode')]:

            if (skip_existing and
                    SettingsModel().get_setting_by_name(k) is not None):
                log.debug('Skipping option %s' % k)
                continue
            setting = RhodeCodeSetting(k, v, t)
            self.sa.add(setting)

    def fixup_groups(self):
        def_usr = User.get_default_user()
        for g in RepoGroup.query().all():
            g.group_name = g.get_new_name(g.name)
            self.sa.add(g)
            # get default perm
            default = UserRepoGroupToPerm.query()\
                .filter(UserRepoGroupToPerm.group == g)\
                .filter(UserRepoGroupToPerm.user == def_usr)\
                .scalar()

            if default is None:
                log.debug('missing default permission for group %s adding' % g)
                perm_obj = RepoGroupModel()._create_default_perms(g)
                self.sa.add(perm_obj)

    def reset_permissions(self, username):
        """
        Resets permissions to default state, useful when old systems had
        bad permissions, we must clean them up

        :param username:
        """
        default_user = User.get_by_username(username)
        if not default_user:
            return

        u2p = UserToPerm.query()\
            .filter(UserToPerm.user == default_user).all()
        fixed = False
        if len(u2p) != len(Permission.DEFAULT_USER_PERMISSIONS):
            for p in u2p:
                Session().delete(p)
            fixed = True
            self.populate_default_permissions()
        return fixed

    def update_repo_info(self):
        RepoModel.update_repoinfo()

    def config_prompt(self, test_repo_path='', retries=3):
        defaults = self.cli_args
        _path = defaults.get('repos_location')
        if retries == 3:
            log.info('Setting up repositories config')

        if _path is not None:
            path = _path
        elif not self.tests and not test_repo_path:
            path = raw_input(
                 'Enter a valid absolute path to store repositories. '
                 'All repositories in that path will be added automatically:'
            )
        else:
            path = test_repo_path
        path_ok = True

        # check proper dir
        if not os.path.isdir(path):
            path_ok = False
            log.error('Given path %s is not a valid directory' % (path,))

        elif not os.path.isabs(path):
            path_ok = False
            log.error('Given path %s is not an absolute path' % (path,))

        # check if path is at least readable.
        if not os.access(path, os.R_OK):
            path_ok = False
            log.error('Given path %s is not readable' % (path,))

        # check write access, warn user about non writeable paths
        elif not os.access(path, os.W_OK) and path_ok:
            log.warning('No write permission to given path %s' % (path,))

            q = ('Given path %s is not writeable, do you want to '
                 'continue with read only mode ? [y/n]' % (path,))
            if not self.ask_ok(q):
                log.error('Canceled by user')
                sys.exit(-1)

        if retries == 0:
            sys.exit('max retries reached')
        if not path_ok:
            retries -= 1
            return self.config_prompt(test_repo_path, retries)

        real_path = os.path.normpath(os.path.realpath(path))

        if real_path != os.path.normpath(path):
            q = ('Path looks like a symlink, RhodeCode Enterprise will store '
                 'given path as %s ? [y/n]') % (real_path,)
            if not self.ask_ok(q):
                log.error('Canceled by user')
                sys.exit(-1)

        return real_path

    def create_settings(self, path):

        self.create_ui_settings(path)

        ui_config = [
            ('web', 'push_ssl', 'false'),
            ('web', 'allow_archive', 'gz zip bz2'),
            ('web', 'allow_push', '*'),
            ('web', 'baseurl', '/'),
            ('paths', '/', path),
            ('phases', 'publish', 'true')
        ]
        for section, key, value in ui_config:
            ui_conf = RhodeCodeUi()
            setattr(ui_conf, 'ui_section', section)
            setattr(ui_conf, 'ui_key', key)
            setattr(ui_conf, 'ui_value', value)
            self.sa.add(ui_conf)

        # rhodecode app settings
        settings = [
            ('realm', 'RhodeCode', 'unicode'),
            ('title', '', 'unicode'),
            ('pre_code', '', 'unicode'),
            ('post_code', '', 'unicode'),
            ('show_public_icon', True, 'bool'),
            ('show_private_icon', True, 'bool'),
            ('stylify_metatags', False, 'bool'),
            ('dashboard_items', 100, 'int'),
            ('admin_grid_items', 25, 'int'),
            ('show_version', True, 'bool'),
            ('use_gravatar', False, 'bool'),
            ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'),
            ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'),
            ('support_url', '', 'unicode'),
            ('update_url', RhodeCodeSetting.DEFAULT_UPDATE_URL, 'unicode'),
            ('show_revision_number', True, 'bool'),
            ('show_sha_length', 12, 'int'),
        ]

        for key, val, type_ in settings:
            sett = RhodeCodeSetting(key, val, type_)
            self.sa.add(sett)

        self.create_auth_plugin_options()
        self.create_default_options()

        log.info('created ui config')

    def create_user(self, username, password, email='', admin=False,
                    strict_creation_check=True, api_key=None):
        log.info('creating user %s' % username)
        user = UserModel().create_or_update(
            username, password, email, firstname='RhodeCode', lastname='Admin',
            active=True, admin=admin, extern_type="rhodecode",
            strict_creation_check=strict_creation_check)

        if api_key:
            log.info('setting a provided api key for the user %s', username)
            user.api_key = api_key

    def create_default_user(self):
        log.info('creating default user')
        # create default user for handling default permissions.
        user = UserModel().create_or_update(username=User.DEFAULT_USER,
                                            password=str(uuid.uuid1())[:20],
                                            email=User.DEFAULT_USER_EMAIL,
                                            firstname='Anonymous',
                                            lastname='User',
                                            strict_creation_check=False)
        # based on configuration options activate/deactive this user which
        # controlls anonymous access
        if self.cli_args.get('public_access') is False:
            log.info('Public access disabled')
            user.active = False
            Session().add(user)
            Session().commit()

    def create_permissions(self):
        """
        Creates all permissions defined in the system
        """
        # module.(access|create|change|delete)_[name]
        # module.(none|read|write|admin)
        log.info('creating permissions')
        PermissionModel(self.sa).create_permissions()

    def populate_default_permissions(self):
        """
        Populate default permissions. It will create only the default
        permissions that are missing, and not alter already defined ones
        """
        log.info('creating default user permissions')
        PermissionModel(self.sa).create_default_user_permissions(user=User.DEFAULT_USER)
Пример #51
0
 def delete(cls, id_):
     obj = cls.query().get(id_)
     Session.delete(obj)
     Session.commit()
Пример #52
0
class AuthnPluginViewBase(object):
    def __init__(self, context, request):
        self.request = request
        self.context = context
        self.plugin = context.plugin
        self._rhodecode_user = request.user

    @LoginRequired()
    @HasPermissionAllDecorator('hg.admin')
    def settings_get(self, defaults=None, errors=None):
        """
        View that displays the plugin settings as a form.
        """
        defaults = defaults or {}
        errors = errors or {}
        schema = self.plugin.get_settings_schema()

        # Compute default values for the form. Priority is:
        # 1. Passed to this method 2. DB value 3. Schema default
        for node in schema:
            if node.name not in defaults:
                defaults[node.name] = self.plugin.get_setting_by_name(
                    node.name, node.default)

        template_context = {
            'defaults': defaults,
            'errors': errors,
            'plugin': self.context.plugin,
            'resource': self.context,
        }

        return template_context

    @LoginRequired()
    @HasPermissionAllDecorator('hg.admin')
    @auth.CSRFRequired()
    def settings_post(self):
        """
        View that validates and stores the plugin settings.
        """
        schema = self.plugin.get_settings_schema()
        data = self.request.params

        try:
            valid_data = schema.deserialize(data)
        except colander.Invalid, e:
            # Display error message and display form again.
            self.request.session.flash(_(
                'Errors exist when saving plugin settings. '
                'Please check the form inputs.'),
                                       queue='error')
            defaults = {key: data[key] for key in data if key in schema}
            return self.settings_get(errors=e.asdict(), defaults=defaults)

        # Store validated data.
        for name, value in valid_data.items():
            self.plugin.create_or_update_setting(name, value)
        Session.commit()

        # Display success message and redirect.
        self.request.session.flash(_('Auth settings updated successfully.'),
                                   queue='success')
        redirect_to = self.request.resource_path(self.context,
                                                 route_name='auth_home')
        return HTTPFound(redirect_to)