Пример #1
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:
            Session.query(cls).filter(cls.users_group_id == users_group_id)\
                .filter(cls.permission == perm).delete()
            Session.commit()
        except:
            Session.rollback()
Пример #2
0
 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
     if case_insensitive:
         gr = Session.query(cls)\
         .filter(cls.users_group_name.ilike(group_name))
     else:
         gr = Session.query(UsersGroup)\
             .filter(UsersGroup.users_group_name == group_name)
     if cache:
         gr = gr.options(FromCache("sql_cache_short",
                                       "get_user_%s" % group_name))
     return gr.scalar()
Пример #3
0
    def _ui(self):
        """
        Creates an db based ui object for this repository
        """
        from mercurial import ui
        from mercurial import config
        baseui = ui.ui()

        #clean the baseui object
        baseui._ocfg = config.config()
        baseui._ucfg = config.config()
        baseui._tcfg = config.config()


        ret = Session.query(RhodeCodeUi)\
            .options(FromCache("sql_cache_short", "repository_repo_ui")).all()

        hg_ui = ret
        for ui_ in hg_ui:
            if ui_.ui_active:
                log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
                          ui_.ui_key, ui_.ui_value)
                baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)

        return baseui
Пример #4
0
    def get_default_group_perms(cls, default_user_id):
        q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
         .filter(UserRepoGroupToPerm.user_id == default_user_id)

        return q.all()
Пример #5
0
    def get_default_repo_perms(cls, default_user_id):
        q = Session.query(UserRepoToPerm, Repository, cls)\
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
         .filter(UserRepoToPerm.user_id == default_user_id)

        return q.all()
Пример #6
0
    def get_default_perms(cls, default_user_id):
        q = Session.query(UserRepoToPerm, Repository, cls)\
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
         .filter(UserRepoToPerm.user_id == default_user_id)

        return q.all()
Пример #7
0
    def get_default_group_perms(cls, default_user_id):
        q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
         .filter(UserRepoGroupToPerm.user_id == default_user_id)

        return q.all()
Пример #8
0
 def get_by_repo_name(cls, repo_name):
     q = Session.query(cls).filter(cls.repo_name == repo_name)
     q = (
         q.options(joinedload(Repository.fork))
         .options(joinedload(Repository.user))
         .options(joinedload(Repository.group))
     )
     return q.one()
Пример #9
0
 def repo_path(self):
     """
     Returns base full path for that repository means where it actually
     exists on a filesystem
     """
     q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == Repository.url_sep())
     q.options(FromCache("sql_cache_short", "repository_repo_path"))
     return q.one().ui_value
Пример #10
0
    def has_perm(cls, users_group_id, perm):
        if not isinstance(perm, Permission):
            raise Exception('perm needs to be an instance of Permission class')

        return Session.query(cls).filter(cls.users_group_id ==
                                         users_group_id)\
                                         .filter(cls.permission == perm)\
                                         .scalar() is not None
Пример #11
0
    def get_ldap_settings(cls, cache=False):
        ret = Session.query(cls)\
                .filter(cls.app_settings_name.startswith('ldap_')).all()
        fd = {}
        for row in ret:
            fd.update({row.app_settings_name:row.app_settings_value})

        return fd
Пример #12
0
 def repo_path(self):
     """
     Returns base full path for that repository means where it actually
     exists on a filesystem
     """
     q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
                                           Repository.url_sep())
     q.options(FromCache("sql_cache_short", "repository_repo_path"))
     return q.one().ui_value
Пример #13
0
    def base_path(cls):
        """
        Returns base path when all repos are stored

        :param cls:
        """
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == cls.url_sep())
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
        return q.one().ui_value
Пример #14
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'})
Пример #15
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()
Пример #16
0
    def base_path(cls):
        """
        Returns base path when all repos are stored

        :param cls:
        """
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
                                              cls.url_sep())
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
        return q.one().ui_value
Пример #17
0
 def invalidate(self):
     """
     Returns Invalidation object if this repo should be invalidated
     None otherwise. `cache_active = False` means that this cache
     state is not valid and needs to be invalidated
     """
     return Session.query(CacheInvalidation)\
         .filter(CacheInvalidation.cache_key == self.repo_name)\
         .filter(CacheInvalidation.cache_active == False)\
         .scalar()
Пример #18
0
 def _get_or_create_key(cls, key, prefix, org_key):
     inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
     if not inv_obj:
         try:
             inv_obj = CacheInvalidation(key, org_key)
             Session.add(inv_obj)
             Session.commit()
         except Exception:
             log.error(traceback.format_exc())
             Session.rollback()
     return inv_obj
Пример #19
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()
Пример #20
0
 def _get_or_create_key(cls, key, prefix, org_key):
     inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
     if not inv_obj:
         try:
             inv_obj = CacheInvalidation(key, org_key)
             Session.add(inv_obj)
             Session.commit()
         except Exception:
             log.error(traceback.format_exc())
             Session.rollback()
     return inv_obj
Пример #21
0
    def get_users(cls, revision):
        """
        Returns user associated with this changesetComment. ie those
        who actually commented

        :param cls:
        :param revision:
        """
        return Session.query(User)\
                .filter(cls.revision == revision)\
                .join(ChangesetComment.author).all()
Пример #22
0
    def get_users(cls, revision):
        """
        Returns user associated with this changesetComment. ie those
        who actually commented

        :param cls:
        :param revision:
        """
        return Session.query(User)\
                .filter(cls.revision == revision)\
                .join(ChangesetComment.author).all()
Пример #23
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'})
Пример #24
0
    def set_invalidate(self):
        """
        set a cache for invalidation for this instance
        """
        inv = Session.query(CacheInvalidation)\
            .filter(CacheInvalidation.cache_key == self.repo_name)\
            .scalar()

        if inv is None:
            inv = CacheInvalidation(self.repo_name)
        inv.cache_active = True
        Session.add(inv)
        Session.commit()
Пример #25
0
    def get_app_settings(cls, cache=False):

        ret = Session.query(cls)

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

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

        return settings
Пример #26
0
    def test_user_notifications(self):
        self.assertEqual([], Notification.query().all())
        self.assertEqual([], UserNotification.query().all())

        notification1 = NotificationModel().create(created_by=self.u1,
                                            subject=u'subj', body=u'hi there1',
                                            recipients=[self.u3])
        Session.commit()
        notification2 = NotificationModel().create(created_by=self.u1,
                                            subject=u'subj', body=u'hi there2',
                                            recipients=[self.u3])
        Session.commit()
        u3 = Session.query(User).get(self.u3)

        self.assertEqual(sorted([x.notification for x in u3.notifications]),
                         sorted([notification2, notification1]))
Пример #27
0
    def test_user_notifications(self):
        self.assertEqual([], Notification.query().all())
        self.assertEqual([], UserNotification.query().all())

        notification1 = NotificationModel().create(created_by=self.u1,
                                                   subject=u'subj',
                                                   body=u'hi there1',
                                                   recipients=[self.u3])
        Session.commit()
        notification2 = NotificationModel().create(created_by=self.u1,
                                                   subject=u'subj',
                                                   body=u'hi there2',
                                                   recipients=[self.u3])
        Session.commit()
        u3 = Session.query(User).get(self.u3)

        self.assertEqual(sorted([x.notification for x in u3.notifications]),
                         sorted([notification2, notification1]))
Пример #28
0
    def set_invalidate(cls, key):
        """
        Mark this Cache key for invalidation

        :param key:
        """

        key, _prefix, _org_key = cls._get_key(key)
        inv_objs = Session.query(cls).filter(cls.cache_args == _org_key).all()
        log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs),
                                                             _org_key))
        try:
            for inv_obj in inv_objs:
                if inv_obj:
                    inv_obj.cache_active = False

                Session.add(inv_obj)
            Session.commit()
        except Exception:
            log.error(traceback.format_exc())
            Session.rollback()
Пример #29
0
    def set_invalidate(cls, key):
        """
        Mark this Cache key for invalidation

        :param key:
        """

        key, _prefix, _org_key = cls._get_key(key)
        inv_objs = Session.query(cls).filter(cls.cache_args == _org_key).all()
        log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs),
                                                             _org_key))
        try:
            for inv_obj in inv_objs:
                if inv_obj:
                    inv_obj.cache_active = False

                Session.add(inv_obj)
            Session.commit()
        except Exception:
            log.error(traceback.format_exc())
            Session.rollback()
Пример #30
0
    def set_invalidate(cls, key):
        """
        Mark this Cache key for invalidation

        :param key:
        """

        log.debug("marking %s for invalidation" % key)
        inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
        if inv_obj:
            inv_obj.cache_active = False
        else:
            log.debug("cache key not found in invalidation db -> creating one")
            inv_obj = CacheInvalidation(key)

        try:
            Session.add(inv_obj)
            Session.commit()
        except Exception:
            log.error(traceback.format_exc())
            Session.rollback()
Пример #31
0
    def set_invalidate(cls, key):
        """
        Mark this Cache key for invalidation

        :param key:
        """

        log.debug('marking %s for invalidation' % key)
        inv_obj = Session.query(cls)\
            .filter(cls.cache_key == key).scalar()
        if inv_obj:
            inv_obj.cache_active = False
        else:
            log.debug('cache key not found in invalidation db -> creating one')
            inv_obj = CacheInvalidation(key)

        try:
            Session.add(inv_obj)
            Session.commit()
        except Exception:
            log.error(traceback.format_exc())
            Session.rollback()
Пример #32
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)
Пример #33
0
 def get_repo_followers(cls, repo_id):
     return Session.query(cls).filter(cls.follows_repo_id == repo_id)
Пример #34
0
 def children(self):
     return Session.query(Group).filter(Group.parent_group == self)
Пример #35
0
class DbManage(object):
    def __init__(self, log_sql, dbconf, root, tests=False):
        self.dbname = dbconf.split("/")[-1]
        self.tests = tests
        self.root = root
        self.dburi = dbconf
        self.log_sql = log_sql
        self.db_exists = False
        self.init_db()

    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, defaults={}):
        """
        Create a auth database
        """
        quiet = defaults.get("quiet")
        log.info("Any existing database is going to be destroyed")
        if self.tests or quiet:
            destroy = True
        else:
            destroy = ask_ok("Are you sure to destroy old database ? [y/n]")
        if not destroy:
            sys.exit()
        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 to version %s" % __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"
                    )

        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:
            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:
            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:
            self.sa.rollback()
            raise

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

            # defaults
            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 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 config_prompt(self, test_repo_path="", retries=3, defaults={}):
        _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 path_ok is False:
            retries -= 1
            return self.config_prompt(test_repo_path, retries)

        real_path = os.path.realpath(path)

        if real_path != 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()

        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)

    def finish(self):
        """
        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")
Пример #36
0
 def query(cls):
     return Session.query(cls)
Пример #37
0
 def query(cls):
     return Session.query(cls)
Пример #38
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')
Пример #39
0
 def get(cls, users_group_id, cache=False):
     users_group = Session.query(cls)
     if cache:
         users_group = users_group.options(FromCache("sql_cache_short",
                                 "get_users_group_%s" % users_group_id))
     return users_group.get(users_group_id)
Пример #40
0
 def get_by_username(cls, username, case_insensitive=False):
     if case_insensitive:
         return Session.query(cls).filter(cls.username.ilike(username)).scalar()
     else:
         return Session.query(cls).filter(cls.username == username).scalar()
Пример #41
0
 def get_repo_forks(cls, repo_id):
     return Session.query(cls).filter(Repository.fork_id == repo_id)
Пример #42
0
 def get_by_username(cls, username, case_insensitive=False):
     if case_insensitive:
         return Session.query(cls).filter(cls.username.ilike(username)).scalar()
     else:
         return Session.query(cls).filter(cls.username == username).scalar()
Пример #43
0
 def get_by_repo_name(cls, repo_name):
     q = Session.query(cls).filter(cls.repo_name == repo_name)
     q = q.options(joinedload(Repository.fork))\
             .options(joinedload(Repository.user))\
             .options(joinedload(Repository.group))
     return q.one()
Пример #44
0
 def get_by_key(cls, key):
     return Session.query(cls).filter(cls.permission_name == key).scalar()
Пример #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
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()
        global ask_ok

        if self.cli_args.get('force_ask') is True:
            ask_ok = lambda *args, **kwargs: True
        elif self.cli_args.get('force_ask') is False:
            ask_ok = lambda *args, **kwargs: False

    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 to version %s' \
                                % __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')

        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:
            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:
            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:
            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 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 path_ok is False:
            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)

    def finish(self):
        """
        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')
Пример #47
0
 def repositories(self):
     return Session.query(Repository).filter(Repository.group == self)