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