X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fcore.cpp;h=4edff846c0e19c8c104e60a3dc6d17d4ab9b2f0f;hp=d613e8f8bf4affa454a51127277b9ae4ef89e3ba;hb=6a63070246d89aa2a2474e3a9a1035fa889ad77e;hpb=32582b14a442c35d1a64131ac10792683fb06f82 diff --git a/src/core/core.cpp b/src/core/core.cpp index d613e8f8..4edff846 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2016 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -184,15 +184,40 @@ Core::Core() void Core::init() { - CoreSettings cs; + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); + bool config_from_environment = Quassel::isOptionSet("config-from-environment"); + + QString db_backend; + QVariantMap db_connectionProperties; + + QString auth_authenticator; + QVariantMap auth_properties; + + bool writeError = false; + + if (config_from_environment) { + db_backend = environment.value("DB_BACKEND"); + auth_authenticator = environment.value("AUTH_AUTHENTICATOR"); + } else { + CoreSettings cs; + + QVariantMap dbsettings = cs.storageSettings().toMap(); + db_backend = dbsettings.value("Backend").toString(); + db_connectionProperties = dbsettings.value("ConnectionProperties").toMap(); + + QVariantMap authSettings = cs.authSettings().toMap(); + auth_authenticator = authSettings.value("Authenticator", "Database").toString(); + auth_properties = authSettings.value("AuthProperties").toMap(); + + writeError = !cs.isWritable(); + } + // legacy - QVariantMap dbsettings = cs.storageSettings().toMap(); - _configured = initStorage(dbsettings.value("Backend").toString(), dbsettings.value("ConnectionProperties").toMap()); + _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment); // Not entirely sure what is 'legacy' about the above, but it seems to be the way things work! if (_configured) { - QVariantMap authSettings = cs.authSettings().toMap(); - initAuthenticator(authSettings.value("Authenticator", "Database").toString(), authSettings.value("AuthProperties").toMap()); + initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment); } if (Quassel::isOptionSet("select-backend") || Quassel::isOptionSet("select-authenticator")) { @@ -206,20 +231,30 @@ void Core::init() } if (!_configured) { - if (_registeredStorageBackends.size() == 0) { - quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); - quWarning() << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" - "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" - "to work.")); - exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) - } - quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; + if (config_from_environment) { + _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true); + initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true); - if (!cs.isWritable()) { - qWarning() << "Cannot write quasselcore configuration; probably a permission problem."; - exit(EXIT_FAILURE); - } + if (!_configured) { + qWarning() << "Cannot configure from environment"; + exit(EXIT_FAILURE); + } + } else { + if (_registeredStorageBackends.empty()) { + quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting...")); + quWarning() + << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n" + "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n" + "to work.")); + exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup) + } + quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup."; + if (writeError) { + qWarning() << "Cannot write quasselcore configuration; probably a permission problem."; + exit(EXIT_FAILURE); + } + } } if (Quassel::isOptionSet("add-user")) { @@ -236,8 +271,12 @@ void Core::init() connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); if (!startListening()) exit(1); // TODO make this less brutal - if (Quassel::isOptionSet("oidentd")) - _oidentdConfigGenerator = new OidentdConfigGenerator(this); + if (Quassel::isOptionSet("oidentd")) { + _oidentdConfigGenerator = new OidentdConfigGenerator(Quassel::isOptionSet("oidentd-strict"), this); + if (Quassel::isOptionSet("oidentd-strict")) { + cacheSysIdent(); + } + } } @@ -255,14 +294,10 @@ Core::~Core() void Core::saveState() { - CoreSettings s; - QVariantMap state; QVariantList activeSessions; foreach(UserId user, instance()->_sessions.keys()) activeSessions << QVariant::fromValue(user); - state["CoreStateVersion"] = 1; - state["ActiveSessions"] = activeSessions; - s.setCoreState(state); + instance()->_storage->setCoreState(activeSessions); } @@ -285,7 +320,9 @@ void Core::restoreState() } */ - QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList(); + const QList &activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList(); + QVariantList activeSessions = instance()->_storage->getCoreState(activeSessionsFallback); + if (activeSessions.count() > 0) { quInfo() << "Restoring previous core state..."; foreach(QVariant v, activeSessions) { @@ -312,12 +349,12 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword, if (adminUser.isEmpty() || adminPassword.isEmpty()) { return tr("Admin user or password not set."); } - if (!(_configured = initStorage(backend, setupData, true))) { + if (!(_configured = initStorage(backend, setupData, {}, false, true))) { return tr("Could not setup storage!"); } quInfo() << "Selected authenticator:" << authenticator; - if (!(_configured = initAuthenticator(authenticator, authSetupData, true))) + if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true))) { return tr("Could not setup authenticator!"); } @@ -329,6 +366,7 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword, quInfo() << qPrintable(tr("Creating admin user...")); _storage->addUser(adminUser, adminPassword); + cacheSysIdent(); startListening(); // TODO check when we need this return QString(); } @@ -338,7 +376,7 @@ QString Core::setupCoreForInternalUsage() { Q_ASSERT(!_registeredStorageBackends.empty()); - qsrand(QDateTime::currentDateTime().toTime_t()); + qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch()); int pass = 0; for (int i = 0; i < 10; i++) { pass *= 10; @@ -383,7 +421,8 @@ DeferredSharedPtr Core::storageBackend(const QString &backendId) const // old db settings: // "Type" => "sqlite" -bool Core::initStorage(const QString &backend, const QVariantMap &settings, bool setup) +bool Core::initStorage(const QString &backend, const QVariantMap &settings, + const QProcessEnvironment &environment, bool loadFromEnvironment, bool setup) { if (backend.isEmpty()) { quWarning() << "No storage backend selected!"; @@ -396,13 +435,13 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings, bool return false; } - Storage::State storageState = storage->init(settings); + Storage::State storageState = storage->init(settings, environment, loadFromEnvironment); switch (storageState) { case Storage::NeedsSetup: if (!setup) return false; // trigger setup process - if (storage->setup(settings)) - return initStorage(backend, settings, false); + if (storage->setup(settings, environment, loadFromEnvironment)) + return initStorage(backend, settings, environment, loadFromEnvironment, false); return false; // if initialization wasn't successful, we quit to keep from coming up unconfigured @@ -480,7 +519,9 @@ DeferredSharedPtr Core::authenticator(const QString &backendId) c // FIXME: Apparently, this is the legacy way of initting storage backends? // If there's a not-legacy way, it should be used here -bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings, bool setup) +bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings, + const QProcessEnvironment &environment, bool loadFromEnvironment, + bool setup) { if (backend.isEmpty()) { quWarning() << "No authenticator selected!"; @@ -493,13 +534,13 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings return false; } - Authenticator::State authState = auth->init(settings); + Authenticator::State authState = auth->init(settings, environment, loadFromEnvironment); switch (authState) { case Authenticator::NeedsSetup: if (!setup) return false; // trigger setup process - if (auth->setup(settings)) - return initAuthenticator(backend, settings, false); + if (auth->setup(settings, environment, loadFromEnvironment)) + return initAuthenticator(backend, settings, environment, loadFromEnvironment, false); return false; // if initialization wasn't successful, we quit to keep from coming up unconfigured @@ -549,6 +590,34 @@ bool Core::reloadCerts() } +void Core::cacheSysIdent() +{ + if (isConfigured()) { + instance()->_authUserNames = instance()->_storage->getAllAuthUserNames(); + } +} + + +QString Core::strictSysIdent(UserId user) const +{ + if (_authUserNames.contains(user)) { + return _authUserNames[user]; + } + + // A new user got added since we last pulled our cache from the database. + // There's no way to avoid a database hit - we don't even know the authname! + cacheSysIdent(); + + if (_authUserNames.contains(user)) { + return _authUserNames[user]; + } + + // ...something very weird is going on if we ended up here (an active CoreSession without a corresponding database entry?) + qWarning().nospace() << "Unable to find authusername for UserId " << user << ", this should never happen!"; + return "unknown"; // Should we just terminate the program instead? +} + + bool Core::startListening() { // in mono mode we only start a local port if a port is specified in the cli call