+
+
+bool Core::changeUserPassword(UserId userId, const QString &password)
+{
+ if (!isConfigured() || !userId.isValid())
+ return false;
+
+ if (!canChangeUserPassword(userId))
+ return false;
+
+ return instance()->_storage->updateUser(userId, password);
+}
+
+// TODO: this code isn't currently 100% optimal because the core
+// doesn't know it can have multiple auth providers configured (there aren't
+// multiple auth providers at the moment anyway) and we have hardcoded the
+// Database provider to be always allowed.
+bool Core::canChangeUserPassword(UserId userId)
+{
+ QString authProvider = instance()->_storage->getUserAuthenticator(userId);
+ if (authProvider != "Database") {
+ if (authProvider != instance()->_authenticator->backendId()) {
+ return false;
+ }
+ else if (instance()->_authenticator->canChangePassword()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage *storage)
+{
+ if (!storage)
+ return nullptr;
+
+ AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+ if (!sqlStorage) {
+ qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
+ return nullptr;
+ }
+
+ return sqlStorage->createMigrationReader();
+}
+
+
+std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage *storage)
+{
+ if (!storage)
+ return nullptr;
+
+ AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+ if (!sqlStorage) {
+ qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
+ return nullptr;
+ }
+
+ return sqlStorage->createMigrationWriter();
+}
+
+
+bool Core::saveBackendSettings(const QString &backend, const QVariantMap &settings)
+{
+ QVariantMap dbsettings;
+ dbsettings["Backend"] = backend;
+ dbsettings["ConnectionProperties"] = settings;
+ CoreSettings s = CoreSettings();
+ s.setStorageSettings(dbsettings);
+ return s.sync();
+}
+
+
+void Core::saveAuthenticatorSettings(const QString &backend, const QVariantMap &settings)
+{
+ QVariantMap dbsettings;
+ dbsettings["Authenticator"] = backend;
+ dbsettings["AuthProperties"] = settings;
+ CoreSettings().setAuthSettings(dbsettings);
+}
+
+// Generic version of promptForSettings that doesn't care what *type* of
+// backend it runs over.
+template<typename Backend>
+QVariantMap Core::promptForSettings(const Backend *backend)
+{
+ QVariantMap settings;
+ const QVariantList& setupData = backend->setupData();
+
+ if (setupData.isEmpty())
+ return settings;
+
+ QTextStream out(stdout);
+ QTextStream in(stdin);
+ out << "Default values are in brackets" << endl;
+
+ for (int i = 0; i + 2 < setupData.size(); i += 3) {
+ QString key = setupData[i].toString();
+ out << setupData[i+1].toString() << " [" << setupData[i+2].toString() << "]: " << flush;
+
+ bool noEcho = key.toLower().contains("password");
+ if (noEcho) {
+ disableStdInEcho();
+ }
+ QString input = in.readLine().trimmed();
+ if (noEcho) {
+ out << endl;
+ enableStdInEcho();
+ }
+
+ QVariant value{setupData[i+2]};
+ if (!input.isEmpty()) {
+ switch (value.type()) {
+ case QVariant::Int:
+ value = input.toInt();
+ break;
+ default:
+ value = input;
+ }
+ }
+ settings[key] = value;
+ }
+ return settings;
+}
+
+
+#ifdef Q_OS_WIN
+void Core::stdInEcho(bool on)
+{
+ HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode = 0;
+ GetConsoleMode(hStdin, &mode);
+ if (on)
+ mode |= ENABLE_ECHO_INPUT;
+ else
+ mode &= ~ENABLE_ECHO_INPUT;
+ SetConsoleMode(hStdin, mode);
+}
+
+#else
+void Core::stdInEcho(bool on)
+{
+ termios t;
+ tcgetattr(STDIN_FILENO, &t);
+ if (on)
+ t.c_lflag |= ECHO;
+ else
+ t.c_lflag &= ~ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, &t);
+}
+
+#endif /* Q_OS_WIN */