示例#1
0
def repo_cnx(config):
    """return a in-memory repository and a repoapi connection to it"""
    from cubicweb import repoapi
    from cubicweb.server.utils import manager_userpasswd
    try:
        login = config.default_admin_config['login']
        pwd = config.default_admin_config['password']
    except KeyError:
        login, pwd = manager_userpasswd()
    while True:
        try:
            repo = repoapi.get_repository(config=config)
            cnx = repoapi.connect(repo, login, password=pwd)
            return repo, cnx
        except AuthenticationError:
            print('-> Error: wrong user/password.')
            # reset cubes else we'll have an assertion error on next retry
            config._cubes = None
        login, pwd = manager_userpasswd()
示例#2
0
 def run(self, args):
     """run the command with its specific arguments"""
     from cubicweb.server.utils import crypt_password, manager_userpasswd
     appid = args[0]
     config = ServerConfiguration.config_for(appid)
     sourcescfg = config.read_sources_file()
     try:
         adminlogin = sourcescfg['admin']['login']
     except KeyError:
         print('-> Error: could not get cubicweb administrator login.')
         sys.exit(1)
     cnx = source_cnx(sourcescfg['system'])
     driver = sourcescfg['system']['db-driver']
     dbhelper = get_db_helper(driver)
     cursor = cnx.cursor()
     # check admin exists
     cursor.execute("SELECT * FROM cw_CWUser WHERE cw_login=%(l)s",
                    {'l': adminlogin})
     if not cursor.fetchall():
         print("-> error: admin user %r specified in sources doesn't exist "
               "in the database" % adminlogin)
         print("   fix your sources file before running this command")
         cnx.close()
         sys.exit(1)
     if self.config.password is None:
         # ask for a new password
         msg = 'new password for %s' % adminlogin
         _, pwd = manager_userpasswd(adminlogin,
                                     confirm=True,
                                     passwdmsg=msg)
     else:
         pwd = self.config.password
     try:
         cursor.execute(
             "UPDATE cw_CWUser SET cw_upassword=%(p)s WHERE cw_login=%(l)s",
             {
                 'p': dbhelper.binary_value(crypt_password(pwd)),
                 'l': adminlogin
             })
         sconfig = Configuration(options=USER_OPTIONS)
         sconfig['login'] = adminlogin
         sconfig['password'] = pwd
         sourcescfg['admin'] = sconfig
         config.write_sources_file(sourcescfg)
     except Exception as ex:
         cnx.rollback()
         import traceback
         traceback.print_exc()
         print('-> an error occurred:', ex)
     else:
         cnx.commit()
         print('-> password reset, sources file regenerated.')
     cnx.close()
示例#3
0
def init_repository(config,
                    interactive=True,
                    drop=False,
                    vreg=None,
                    init_config=None):
    """Initialise a repository database by creating tables and filling them
    with the minimal set of entities (ie at least the schema, base groups and
    a initial user)
    """
    from cubicweb.repoapi import get_repository, connect
    from cubicweb.server.repository import Repository
    from cubicweb.server.utils import manager_userpasswd
    from cubicweb.server.sqlutils import sqlexec, sqlschema, sql_drop_all_user_tables
    from cubicweb.server.sqlutils import _SQL_DROP_ALL_USER_TABLES_FILTER_FUNCTION as drop_filter
    # configuration to avoid db schema loading and user'state checking
    # on connection
    config.creating = True
    config.consider_user_state = False
    config.cubicweb_appobject_path = set(('hooks', 'entities'))
    config.cube_appobject_path = set(('hooks', 'entities'))
    # only enable the system source at initialization time
    repo = Repository(config, vreg=vreg)
    repo.bootstrap()
    if init_config is not None:
        # further config initialization once it has been bootstrapped
        init_config(config)
    schema = repo.schema
    sourcescfg = config.read_sources_file()
    source = sourcescfg['system']
    driver = source['db-driver']
    with repo.internal_cnx() as cnx:
        sqlcnx = cnx.cnxset.cnx
        sqlcursor = cnx.cnxset.cu
        execute = sqlcursor.execute
        if drop:
            helper = database.get_db_helper(driver)
            dropsql = sql_drop_all_user_tables(helper, sqlcursor)
            # We may fail dropping some tables because of table dependencies, in a first pass.
            # So, we try a second drop sequence to drop remaining tables if needed.
            # Note that 2 passes is an arbitrary choice as it seems enough for our usecases
            # (looping may induce infinite recursion when user have no rights for example).
            # Here we try to keep code simple and backend independent. That's why we don't try to
            # distinguish remaining tables (missing privileges, dependencies, ...).
            failed = sqlexec(dropsql,
                             execute,
                             cnx=sqlcnx,
                             pbtitle='-> dropping tables (first pass)')
            if failed:
                failed = sqlexec(failed,
                                 execute,
                                 cnx=sqlcnx,
                                 pbtitle='-> dropping tables (second pass)')
                remainings = list(
                    filter(drop_filter, helper.list_tables(sqlcursor)))
                assert not remainings, 'Remaining tables: %s' % ', '.join(
                    remainings)
        handler = config.migration_handler(schema,
                                           interactive=False,
                                           repo=repo,
                                           cnx=cnx)
        # install additional driver specific sql files
        handler.cmd_install_custom_sql_scripts()
        for cube in reversed(config.cubes()):
            handler.cmd_install_custom_sql_scripts(cube)
        _title = '-> creating tables '
        print(_title, end=' ')
        # schema entities and relations tables
        # can't skip entities table even if system source doesn't support them,
        # they are used sometimes by generated sql. Keeping them empty is much
        # simpler than fixing this...
        schemasql = sqlschema(schema, driver)
        failed = sqlexec(schemasql, execute, pbtitle=_title)
        if failed:
            print(
                'The following SQL statements failed. You should check your schema.'
            )
            print(failed)
            raise Exception(
                'execution of the sql schema failed, you should check your schema'
            )
        sqlcursor.close()
        sqlcnx.commit()
    with repo.internal_cnx() as cnx:
        # insert entity representing the system source
        ssource = cnx.create_entity('CWSource', type=u'native', name=u'system')
        repo.system_source.eid = ssource.eid
        cnx.execute('SET X cw_source X WHERE X eid %(x)s', {'x': ssource.eid})
        # insert base groups and default admin
        print('-> inserting default user and default groups.')
        try:
            login = sourcescfg['admin']['login']
            pwd = sourcescfg['admin']['password']
        except KeyError:
            if interactive:
                msg = 'enter login and password of the initial manager account'
                login, pwd = manager_userpasswd(msg=msg, confirm=True)
            else:
                login, pwd = source['db-user'], source['db-password']
        # sort for eid predicatability as expected in some server tests
        for group in sorted(BASE_GROUPS):
            cnx.create_entity('CWGroup', name=group)
        admin = create_user(cnx, login, pwd, u'managers')
        cnx.execute(
            'SET X owned_by U WHERE X is IN (CWGroup,CWSource), U eid %(u)s',
            {'u': admin.eid})
        cnx.commit()
    repo.shutdown()
    # re-login using the admin user
    config._cubes = None  # avoid assertion error
    repo = get_repository(config=config)
    # replace previous schema by the new repo's one. This is necessary so that we give the proper
    # schema to `initialize_schema` above since it will initialize .eid attribute of schema elements
    schema = repo.schema
    with connect(repo, login, password=pwd) as cnx:
        with cnx.security_enabled(False, False):
            repo.system_source.eid = ssource.eid  # redo this manually
            handler = config.migration_handler(schema,
                                               interactive=False,
                                               cnx=cnx,
                                               repo=repo)
            # serialize the schema
            initialize_schema(config, schema, handler)
            # yoo !
            cnx.commit()
            repo.system_source.init_creating()
            cnx.commit()
    repo.shutdown()
    # restore initial configuration
    config.creating = False
    config.consider_user_state = True
    # (drop instance attribute to get back to class attribute)
    del config.cubicweb_appobject_path
    del config.cube_appobject_path
    print('-> database for instance %s initialized.' % config.appid)