-// Potentially called during the initialization phase (before handing the connection off to the session)
-void Core::clientDisconnected() {
- QTcpSocket *socket = dynamic_cast<QTcpSocket*>(sender()); // Note: This might be a QObject* already (if called by ~Core())!
- Q_ASSERT(socket);
- blocksizes.remove(socket);
- clientInfo.remove(socket);
- qDebug() << qPrintable(tr("Non-authed client disconnected."));
- socket->deleteLater();
- socket = 0;
-
- // make server listen again if still not configured
- if (!configured) {
- startListening();
- }
-
- // TODO remove unneeded sessions - if necessary/possible...
- // Suggestion: kill sessions if they are not connected to any network and client.
-}
-
-void Core::setupClientSession(QTcpSocket *socket, UserId uid) {
- // Find or create session for validated user
- SessionThread *sess;
- if(sessions.contains(uid)) sess = sessions[uid];
- else sess = createSession(uid);
- // Hand over socket, session then sends state itself
- disconnect(socket, 0, this, 0);
- blocksizes.remove(socket);
- clientInfo.remove(socket);
- if(!sess) {
- qWarning() << qPrintable(tr("Could not initialize session for client %1!").arg(socket->peerAddress().toString()));
- socket->close();
- }
- sess->addClient(socket);
-}
-
-SessionThread *Core::createSession(UserId uid, bool restore) {
- if(sessions.contains(uid)) {
- qWarning() << "Calling createSession() when a session for the user already exists!";
- return 0;
- }
- SessionThread *sess = new SessionThread(uid, restore, this);
- sessions[uid] = sess;
- sess->start();
- return sess;
+
+// migration / backend selection
+bool Core::selectBackend(const QString &backend)
+{
+ // reregister all storage backends
+ registerStorageBackends();
+ if (!_storageBackends.contains(backend)) {
+ qWarning() << qPrintable(QString("Core::selectBackend(): unsupported backend: %1").arg(backend));
+ qWarning() << " supported backends are:" << qPrintable(QStringList(_storageBackends.keys()).join(", "));
+ return false;
+ }
+
+ Storage *storage = _storageBackends[backend];
+ QVariantMap settings = promptForSettings(storage);
+
+ Storage::State storageState = storage->init(settings);
+ switch (storageState) {
+ case Storage::IsReady:
+ saveBackendSettings(backend, settings);
+ qWarning() << "Switched backend to:" << qPrintable(backend);
+ qWarning() << "Backend already initialized. Skipping Migration";
+ return true;
+ case Storage::NotAvailable:
+ qCritical() << "Backend is not available:" << qPrintable(backend);
+ return false;
+ case Storage::NeedsSetup:
+ if (!storage->setup(settings)) {
+ qWarning() << qPrintable(QString("Core::selectBackend(): unable to setup backend: %1").arg(backend));
+ return false;
+ }
+
+ if (storage->init(settings) != Storage::IsReady) {
+ qWarning() << qPrintable(QString("Core::migrateBackend(): unable to initialize backend: %1").arg(backend));
+ return false;
+ }
+
+ saveBackendSettings(backend, settings);
+ qWarning() << "Switched backend to:" << qPrintable(backend);
+ break;
+ }
+
+ // let's see if we have a current storage object we can migrate from
+ AbstractSqlMigrationReader *reader = getMigrationReader(_storage);
+ AbstractSqlMigrationWriter *writer = getMigrationWriter(storage);
+ if (reader && writer) {
+ qDebug() << qPrintable(QString("Migrating Storage backend %1 to %2...").arg(_storage->displayName(), storage->displayName()));
+ delete _storage;
+ _storage = 0;
+ delete storage;
+ storage = 0;
+ if (reader->migrateTo(writer)) {
+ qDebug() << "Migration finished!";
+ saveBackendSettings(backend, settings);
+ return true;
+ }
+ return false;
+ qWarning() << qPrintable(QString("Core::migrateDb(): unable to migrate storage backend! (No migration writer for %1)").arg(backend));
+ }
+
+ // inform the user why we cannot merge
+ if (!_storage) {
+ qWarning() << "No currently active backend. Skipping migration.";
+ }
+ else if (!reader) {
+ qWarning() << "Currently active backend does not support migration:" << qPrintable(_storage->displayName());
+ }
+ if (writer) {
+ qWarning() << "New backend does not support migration:" << qPrintable(backend);
+ }
+
+ // so we were unable to merge, but let's create a user \o/
+ _storage = storage;
+ createUser();
+ return true;
+}
+
+
+bool Core::createUser()
+{
+ QTextStream out(stdout);
+ QTextStream in(stdin);
+ out << "Add a new user:" << endl;
+ out << "Username: ";
+ out.flush();
+ QString username = in.readLine().trimmed();
+
+ disableStdInEcho();
+ out << "Password: ";
+ out.flush();
+ QString password = in.readLine().trimmed();
+ out << endl;
+ out << "Repeat Password: ";
+ out.flush();
+ QString password2 = in.readLine().trimmed();
+ out << endl;
+ enableStdInEcho();
+
+ if (password != password2) {
+ qWarning() << "Passwords don't match!";
+ return false;
+ }
+ if (password.isEmpty()) {
+ qWarning() << "Password is empty!";
+ return false;
+ }
+
+ if (_configured && _storage->addUser(username, password).isValid()) {
+ out << "Added user " << username << " successfully!" << endl;
+ return true;
+ }
+ else {
+ qWarning() << "Unable to add user:" << qPrintable(username);
+ return false;
+ }
+}
+
+
+bool Core::changeUserPass(const QString &username)
+{
+ QTextStream out(stdout);
+ QTextStream in(stdin);
+ UserId userId = _storage->getUserId(username);
+ if (!userId.isValid()) {
+ out << "User " << username << " does not exist." << endl;
+ return false;
+ }
+
+ out << "Change password for user: " << username << endl;
+
+ disableStdInEcho();
+ out << "New Password: ";
+ out.flush();
+ QString password = in.readLine().trimmed();
+ out << endl;
+ out << "Repeat Password: ";
+ out.flush();
+ QString password2 = in.readLine().trimmed();
+ out << endl;
+ enableStdInEcho();
+
+ if (password != password2) {
+ qWarning() << "Passwords don't match!";
+ return false;
+ }
+ if (password.isEmpty()) {
+ qWarning() << "Password is empty!";
+ return false;
+ }
+
+ if (_configured && _storage->updateUser(userId, password)) {
+ out << "Password changed successfully!" << endl;
+ return true;
+ }
+ else {
+ qWarning() << "Failed to change password!";
+ return false;
+ }
+}
+
+
+bool Core::changeUserPassword(UserId userId, const QString &password)
+{
+ if (!isConfigured() || !userId.isValid())
+ return false;
+
+ return instance()->_storage->updateUser(userId, password);