/***************************************************************************
- * 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 *
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")) {
}
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")) {
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();
+ }
+ }
}
void Core::saveState()
{
- CoreSettings s;
- QVariantMap state;
QVariantList activeSessions;
foreach(UserId user, instance()->_sessions.keys())
activeSessions << QVariant::fromValue<UserId>(user);
- state["CoreStateVersion"] = 1;
- state["ActiveSessions"] = activeSessions;
- s.setCoreState(state);
+ instance()->_storage->setCoreState(activeSessions);
}
}
*/
- QVariantList activeSessions = s.coreState().toMap()["ActiveSessions"].toList();
+ const QList<QVariant> &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) {
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!");
}
quInfo() << qPrintable(tr("Creating admin user..."));
_storage->addUser(adminUser, adminPassword);
+ cacheSysIdent();
startListening(); // TODO check when we need this
return QString();
}
{
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;
// 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!";
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
case Storage::NotAvailable:
qCritical() << "FATAL: Selected storage backend is not available:" << backend;
- exit(EXIT_FAILURE);
+ if (!setup)
+ exit(EXIT_FAILURE);
+ return false;
+
case Storage::IsReady:
// delete all other backends
_registeredStorageBackends.clear();
// 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!";
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
case Authenticator::NotAvailable:
qCritical() << "FATAL: Selected auth backend is not available:" << backend;
- exit(EXIT_FAILURE);
+ if (!setup)
+ exit(EXIT_FAILURE);
+ return false;
+
case Authenticator::IsReady:
// delete all other backends
_registeredAuthenticators.clear();
}
+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