Пример #1
0
    def update_lastlogin(self):
        """Update user lastlogin"""

        self.last_login = datetime.datetime.now()
        Session.add(self)
        Session.commit()
        log.debug("updated user %s lastlogin" % self.username)
Пример #2
0
    def update_lastlogin(self):
        """Update user lastlogin"""

        self.last_login = datetime.datetime.now()
        Session.add(self)
        Session.commit()
        log.debug('updated user %s lastlogin' % self.username)
Пример #3
0
 def add_user_to_group(group, user):
     ugm = UsersGroupMember()
     ugm.users_group = group
     ugm.user = user
     Session.add(ugm)
     Session.commit()
     return ugm
Пример #4
0
 def create(cls, users_group, repository, permission):
     n = cls()
     n.users_group = users_group
     n.repository = repository
     n.permission = permission
     Session.add(n)
     return n
Пример #5
0
 def create(cls, users_group, repository, permission):
     n = cls()
     n.users_group = users_group
     n.repository = repository
     n.permission = permission
     Session.add(n)
     return n
Пример #6
0
 def add_user_to_group(group, user):
     ugm = UserGroupMember()
     ugm.users_group = group
     ugm.user = user
     Session.add(ugm)
     Session.commit()
     return ugm
Пример #7
0
    def create_or_update_hook(cls, key, val):
        new_ui = cls.get_by_key(key).scalar() or cls()
        new_ui.ui_section = 'hooks'
        new_ui.ui_active = True
        new_ui.ui_key = key
        new_ui.ui_value = val

        Session.add(new_ui)
Пример #8
0
    def create_or_update_hook(cls, key, val):
        new_ui = cls.get_by_key(key).scalar() or cls()
        new_ui.ui_section = 'hooks'
        new_ui.ui_active = True
        new_ui.ui_key = key
        new_ui.ui_value = val

        Session.add(new_ui)
Пример #9
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()
Пример #10
0
    def set_valid(cls, key):
        """
        Mark this cache key as active and currently cached

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

        :param key:
        """
        inv_obj = cls.get_by_key(key)
        inv_obj.cache_active = True
        Session.add(inv_obj)
        Session.commit()
Пример #12
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
Пример #13
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()
Пример #14
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
Пример #15
0
    def create(cls, form_data):
        try:
            new_users_group = cls()
            for k, v in form_data.items():
                setattr(new_users_group, k, v)

            Session.add(new_users_group)
            Session.commit()
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #16
0
    def grant_perm(cls, users_group_id, perm):
        if not isinstance(perm, Permission):
            raise Exception('perm needs to be an instance of Permission class')

        new = cls()
        new.users_group_id = users_group_id
        new.permission = perm
        try:
            Session.add(new)
            Session.commit()
        except:
            Session.rollback()
Пример #17
0
    def grant_perm(cls, users_group_id, perm):
        if not isinstance(perm, Permission):
            raise Exception("perm needs to be an instance of Permission class")

        new = cls()
        new.users_group_id = users_group_id
        new.permission = perm
        try:
            Session.add(new)
            Session.commit()
        except:
            Session.rollback()
Пример #18
0
    def set_invalidate(self):
        """
        set a cache for invalidation for this instance
        """
        inv = CacheInvalidation.query()\
            .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()
Пример #19
0
 def update_user_permission(self, repository, user, permission):
     permission = Permission.get_by_key(permission)
     current = self.get_user_permission(repository, user)
     if current:
         if not current.permission is permission:
             current.permission = permission
     else:
         p = RepoToPerm()
         p.user = user
         p.repository = repository
         p.permission = permission
         Session.add(p)
     Session.commit()
Пример #20
0
    def create(cls, form_data):
        try:
            new_users_group = cls()
            for k, v in form_data.items():
                setattr(new_users_group, k, v)

            Session.add(new_users_group)
            Session.commit()
            return new_users_group
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #21
0
    def create(cls, created_by, subject, body, recipients, type_=None):
        if type_ is None:
            type_ = Notification.TYPE_MESSAGE

        notification = cls()
        notification.created_by_user = created_by
        notification.subject = subject
        notification.body = body
        notification.type_ = type_
        notification.created_on = datetime.datetime.now()

        for u in recipients:
            assoc = UserNotification()
            assoc.notification = notification
            u.notifications.append(assoc)
        Session.add(notification)
        return notification
Пример #22
0
    def create(cls, created_by, subject, body, recipients, type_=None):
        if type_ is None:
            type_ = Notification.TYPE_MESSAGE

        notification = cls()
        notification.created_by_user = created_by
        notification.subject = subject
        notification.body = body
        notification.type_ = type_
        notification.created_on = datetime.datetime.now()

        for u in recipients:
            assoc = UserNotification()
            assoc.notification = notification
            u.notifications.append(assoc)
        Session.add(notification)
        return notification
Пример #23
0
    def create(cls, form_data):
        from rhodecode.lib.auth import get_crypt_password

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

            new_user.api_key = generate_api_key(form_data["username"])
            Session.add(new_user)
            Session.commit()
            return new_user
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #24
0
    def create(cls, form_data):
        from rhodecode.lib.auth import get_crypt_password

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

            new_user.api_key = generate_auth_token(form_data['username'])
            Session.add(new_user)
            Session.commit()
            return new_user
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #25
0
    def scm_instance_cached(self):
        @cache_region('long_term')
        def _c(repo_name):
            return self.__get_instance()

        # TODO: remove this trick when beaker 1.6 is released
        # and have fixed this issue with not supporting unicode keys
        rn = safe_str(self.repo_name)

        inv = self.invalidate
        if inv is not None:
            region_invalidate(_c, None, rn)
            # update our cache
            inv.cache_active = True
            Session.add(inv)
            Session.commit()

        return _c(rn)
Пример #26
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()
Пример #27
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()
Пример #28
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()
Пример #29
0
    def settings_labs_update(self):
        """POST /admin/settings/labs: All items in the collection"""
        # url('admin_settings/labs', method={'POST'})
        c.active = 'labs'

        application_form = LabsSettingsForm()()
        try:
            form_result = application_form.to_python(dict(request.POST))
        except formencode.Invalid as errors:
            h.flash(_('Some form inputs contain invalid data.'),
                    category='error')
            return htmlfill.render(render('admin/settings/settings.html'),
                                   defaults=errors.value,
                                   errors=errors.error_dict or {},
                                   prefix_error=False,
                                   encoding='UTF-8',
                                   force_defaults=False)

        try:
            session = Session()
            for setting in _LAB_SETTINGS:
                setting_name = setting.key[len('rhodecode_'):]
                sett = SettingsModel().create_or_update_setting(
                    setting_name, form_result[setting.key], setting.type)
                session.add(sett)

        except Exception:
            log.exception('Exception while updating lab settings')
            h.flash(_('Error occurred during updating labs settings'),
                    category='error')
        else:
            Session().commit()
            SettingsModel().invalidate_settings_cache()
            h.flash(_('Updated Labs settings'), category='success')
            return redirect(url('admin_settings_labs'))

        return htmlfill.render(render('admin/settings/settings.html'),
                               defaults=self._form_defaults(),
                               encoding='UTF-8',
                               force_defaults=False)
Пример #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 create_or_update_setting(
            self, name, val=Optional(''), type_=Optional('unicode')):
        """
        Creates or updates RhodeCode setting. If updates is triggered it will
        only update parameters that are explicityl set Optional instance will
        be skipped

        :param name:
        :param val:
        :param type_:
        :return:
        """

        res = self.get_setting_by_name(name)
        repo = self._get_repo(self.repo) if self.repo else None

        if not res:
            val = Optional.extract(val)
            type_ = Optional.extract(type_)

            args = (
                (repo.repo_id, name, val, type_)
                if repo else (name, val, type_))
            res = self.SettingsDbModel(*args)

        else:
            if self.repo:
                res.repository_id = repo.repo_id

            res.app_settings_name = name
            if not isinstance(type_, Optional):
                # update if set
                res.app_settings_type = type_
            if not isinstance(val, Optional):
                # update if set
                res.app_settings_value = val

        Session.add(res)
        return res
Пример #32
0
    def update(cls, users_group_id, form_data):

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

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

            Session.add(users_group)
            Session.commit()
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #33
0
    def update(cls, users_group_id, form_data):

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

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

            Session.add(users_group)
            Session.commit()
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #34
0
    def update(cls, users_group_id, form_data):

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

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

            Session.add(users_group)
            Session.commit()
        except:
            log.error(traceback.format_exc())
            Session.rollback()
            raise
Пример #35
0
 def mark_as_read(self):
     self.read = True
     Session.add(self)
Пример #36
0
 def mark_as_read(self):
     self.read = True
     Session.add(self)
Пример #37
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')
Пример #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()
        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')
Пример #39
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")
Пример #40
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')
Пример #41
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)
Пример #42
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')