def revoke_perm(cls, users_group_id, perm): if not isinstance(perm, Permission): raise Exception('perm needs to be an instance of Permission class') try: Session.query(cls).filter(cls.users_group_id == users_group_id)\ .filter(cls.permission == perm).delete() Session.commit() except: Session.rollback()
def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): if case_insensitive: gr = Session.query(cls)\ .filter(cls.users_group_name.ilike(group_name)) else: gr = Session.query(UsersGroup)\ .filter(UsersGroup.users_group_name == group_name) if cache: gr = gr.options(FromCache("sql_cache_short", "get_user_%s" % group_name)) return gr.scalar()
def _ui(self): """ Creates an db based ui object for this repository """ from mercurial import ui from mercurial import config baseui = ui.ui() #clean the baseui object baseui._ocfg = config.config() baseui._ucfg = config.config() baseui._tcfg = config.config() ret = Session.query(RhodeCodeUi)\ .options(FromCache("sql_cache_short", "repository_repo_ui")).all() hg_ui = ret for ui_ in hg_ui: if ui_.ui_active: log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, ui_.ui_key, ui_.ui_value) baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value) return baseui
def get_default_group_perms(cls, default_user_id): q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\ .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\ .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\ .filter(UserRepoGroupToPerm.user_id == default_user_id) return q.all()
def get_default_repo_perms(cls, default_user_id): q = Session.query(UserRepoToPerm, Repository, cls)\ .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ .filter(UserRepoToPerm.user_id == default_user_id) return q.all()
def get_default_perms(cls, default_user_id): q = Session.query(UserRepoToPerm, Repository, cls)\ .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\ .filter(UserRepoToPerm.user_id == default_user_id) return q.all()
def get_by_repo_name(cls, repo_name): q = Session.query(cls).filter(cls.repo_name == repo_name) q = ( q.options(joinedload(Repository.fork)) .options(joinedload(Repository.user)) .options(joinedload(Repository.group)) ) return q.one()
def repo_path(self): """ Returns base full path for that repository means where it actually exists on a filesystem """ q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == Repository.url_sep()) q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value
def has_perm(cls, users_group_id, perm): if not isinstance(perm, Permission): raise Exception('perm needs to be an instance of Permission class') return Session.query(cls).filter(cls.users_group_id == users_group_id)\ .filter(cls.permission == perm)\ .scalar() is not None
def get_ldap_settings(cls, cache=False): ret = Session.query(cls)\ .filter(cls.app_settings_name.startswith('ldap_')).all() fd = {} for row in ret: fd.update({row.app_settings_name:row.app_settings_value}) return fd
def base_path(cls): """ Returns base path when all repos are stored :param cls: """ q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == cls.url_sep()) q.options(FromCache("sql_cache_short", "repository_repo_path")) return q.one().ui_value
def test_repo_group_user_as_user_group_member(self): # create Group1 self.g1 = _make_group('group1', skip_if_exists=True) Session.commit() a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.read'}) # set default permission to none ReposGroupModel().grant_user_permission(repos_group=self.g1, user=self.anon, perm='group.none') # make group self.ug1 = UsersGroupModel().create('G1') # add user to group UsersGroupModel().add_user_to_group(self.ug1, self.u1) Session.commit() # check if user is in the group membrs = [ x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members ] self.assertEqual(membrs, [self.u1.user_id]) # add some user to that group # check his permissions a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) # grant ug1 read permissions for ReposGroupModel().grant_users_group_permission(repos_group=self.g1, group_name=self.ug1, perm='group.read') Session.commit() # check if the obj = Session.query(UsersGroupRepoGroupToPerm)\ .filter(UsersGroupRepoGroupToPerm.group == self.g1)\ .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\ .scalar() self.assertEqual(obj.permission.permission_name, 'group.read') a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.read'})
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()
def invalidate(self): """ Returns Invalidation object if this repo should be invalidated None otherwise. `cache_active = False` means that this cache state is not valid and needs to be invalidated """ return Session.query(CacheInvalidation)\ .filter(CacheInvalidation.cache_key == self.repo_name)\ .filter(CacheInvalidation.cache_active == False)\ .scalar()
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
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()
def get_users(cls, revision): """ Returns user associated with this changesetComment. ie those who actually commented :param cls: :param revision: """ return Session.query(User)\ .filter(cls.revision == revision)\ .join(ChangesetComment.author).all()
def test_repo_group_user_as_user_group_member(self): # create Group1 self.g1 = _make_group('group1', skip_if_exists=True) Session.commit() a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.read'}) # set default permission to none ReposGroupModel().grant_user_permission(repos_group=self.g1, user=self.anon, perm='group.none') # make group self.ug1 = UsersGroupModel().create('G1') # add user to group UsersGroupModel().add_user_to_group(self.ug1, self.u1) Session.commit() # check if user is in the group membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members] self.assertEqual(membrs, [self.u1.user_id]) # add some user to that group # check his permissions a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) # grant ug1 read permissions for ReposGroupModel().grant_users_group_permission(repos_group=self.g1, group_name=self.ug1, perm='group.read') Session.commit() # check if the obj = Session.query(UsersGroupRepoGroupToPerm)\ .filter(UsersGroupRepoGroupToPerm.group == self.g1)\ .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\ .scalar() self.assertEqual(obj.permission.permission_name, 'group.read') a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.read'})
def set_invalidate(self): """ set a cache for invalidation for this instance """ inv = Session.query(CacheInvalidation)\ .filter(CacheInvalidation.cache_key == self.repo_name)\ .scalar() if inv is None: inv = CacheInvalidation(self.repo_name) inv.cache_active = True Session.add(inv) Session.commit()
def get_app_settings(cls, cache=False): ret = Session.query(cls) if cache: ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) if not ret: raise Exception('Could not get application settings !') settings = {} for each in ret: settings['rhodecode_' + each.app_settings_name] = \ each.app_settings_value return settings
def test_user_notifications(self): self.assertEqual([], Notification.query().all()) self.assertEqual([], UserNotification.query().all()) notification1 = NotificationModel().create(created_by=self.u1, subject=u'subj', body=u'hi there1', recipients=[self.u3]) Session.commit() notification2 = NotificationModel().create(created_by=self.u1, subject=u'subj', body=u'hi there2', recipients=[self.u3]) Session.commit() u3 = Session.query(User).get(self.u3) self.assertEqual(sorted([x.notification for x in u3.notifications]), sorted([notification2, notification1]))
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()
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()
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()
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)
def get_repo_followers(cls, repo_id): return Session.query(cls).filter(cls.follows_repo_id == repo_id)
def children(self): return Session.query(Group).filter(Group.parent_group == self)
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")
def query(cls): return Session.query(cls)
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')
def get(cls, users_group_id, cache=False): users_group = Session.query(cls) if cache: users_group = users_group.options(FromCache("sql_cache_short", "get_users_group_%s" % users_group_id)) return users_group.get(users_group_id)
def get_by_username(cls, username, case_insensitive=False): if case_insensitive: return Session.query(cls).filter(cls.username.ilike(username)).scalar() else: return Session.query(cls).filter(cls.username == username).scalar()
def get_repo_forks(cls, repo_id): return Session.query(cls).filter(Repository.fork_id == repo_id)
def get_by_repo_name(cls, repo_name): q = Session.query(cls).filter(cls.repo_name == repo_name) q = q.options(joinedload(Repository.fork))\ .options(joinedload(Repository.user))\ .options(joinedload(Repository.group)) return q.one()
def get_by_key(cls, key): return Session.query(cls).filter(cls.permission_name == key).scalar()
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')
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')
def repositories(self): return Session.query(Repository).filter(Repository.group == self)