/***************************************************************************
- * Copyright (C) 2005-2015 by the Quassel Project *
+ * Copyright (C) 2005-2016 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
}
-AbstractSqlMigrationWriter *PostgreSqlStorage::createMigrationWriter()
+std::unique_ptr<AbstractSqlMigrationWriter> PostgreSqlStorage::createMigrationWriter()
{
- PostgreSqlMigrationWriter *writer = new PostgreSqlMigrationWriter();
+ auto writer = new PostgreSqlMigrationWriter();
QVariantMap properties;
properties["Username"] = _userName;
properties["Password"] = _password;
properties["Port"] = _port;
properties["Database"] = _databaseName;
writer->setConnectionProperties(properties);
- return writer;
+ return std::unique_ptr<AbstractSqlMigrationWriter>{writer};
}
bool PostgreSqlStorage::isAvailable() const
{
- qDebug() << QSqlDatabase::drivers();
- if (!QSqlDatabase::isDriverAvailable("QPSQL")) return false;
+ if (!QSqlDatabase::isDriverAvailable("QPSQL")) {
+ quWarning() << qPrintable(tr("PostgreSQL driver plugin not available for Qt. Installed drivers:"))
+ << qPrintable(QSqlDatabase::drivers().join(", "));
+ return false;
+ }
return true;
}
-QString PostgreSqlStorage::displayName() const
+QString PostgreSqlStorage::backendId() const
{
return QString("PostgreSQL");
}
-QString PostgreSqlStorage::description() const
+QString PostgreSqlStorage::displayName() const
{
- // FIXME: proper description
- return tr("PostgreSQL Turbo Bomber HD!");
+ return backendId(); // Note: Pre-0.13 clients use the displayName property for backend idenfication
}
-QStringList PostgreSqlStorage::setupKeys() const
+QString PostgreSqlStorage::description() const
{
- QStringList keys;
- keys << "Username"
- << "Password"
- << "Hostname"
- << "Port"
- << "Database";
- return keys;
+ // FIXME: proper description
+ return tr("PostgreSQL Turbo Bomber HD!");
}
-QVariantMap PostgreSqlStorage::setupDefaults() const
+QVariantList PostgreSqlStorage::setupData() const
{
- QVariantMap map;
- map["Username"] = QVariant(QString("quassel"));
- map["Hostname"] = QVariant(QString("localhost"));
- map["Port"] = QVariant(5432);
- map["Database"] = QVariant(QString("quassel"));
- return map;
+ QVariantList data;
+ data << "Username" << tr("Username") << QString("quassel")
+ << "Password" << tr("Password") << QString()
+ << "Hostname" << tr("Hostname") << QString("localhost")
+ << "Port" << tr("Port") << 5432
+ << "Database" << tr("Database") << QString("quassel")
+ ;
+ return data;
}
}
-UserId PostgreSqlStorage::addUser(const QString &user, const QString &password)
+UserId PostgreSqlStorage::addUser(const QString &user, const QString &password, const QString &authenticator)
{
QSqlQuery query(logDb());
query.prepare(queryString("insert_quasseluser"));
query.bindValue(":username", user);
query.bindValue(":password", hashPassword(password));
query.bindValue(":hashversion", Storage::HashVersion::Latest);
+ query.bindValue(":authenticator", authenticator);
safeExec(query);
if (!watchQuery(query))
return 0;
}
}
+QString PostgreSqlStorage::getUserAuthenticator(const UserId userid)
+{
+ QSqlQuery query(logDb());
+ query.prepare(queryString("select_authenticator"));
+ query.bindValue(":userid", userid.toInt());
+ safeExec(query);
+ watchQuery(query);
+
+ if (query.first()) {
+ return query.value(0).toString();
+ }
+ else {
+ return QString("");
+ }
+}
UserId PostgreSqlStorage::internalUser()
{
query.bindValue(":autoreconnectretries", info.autoReconnectRetries);
query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries);
query.bindValue(":rejoinchannels", info.rejoinChannels);
+ // Custom rate limiting
+ query.bindValue(":usecustomessagerate", info.useCustomMessageRate);
+ query.bindValue(":messagerateburstsize", info.messageRateBurstSize);
+ query.bindValue(":messageratedelay", info.messageRateDelay);
+ query.bindValue(":unlimitedmessagerate", info.unlimitedMessageRate);
if (info.networkId.isValid())
query.bindValue(":networkid", info.networkId.toInt());
}
query.bindValue(":proxyport", server.proxyPort);
query.bindValue(":proxyuser", server.proxyUser);
query.bindValue(":proxypass", server.proxyPass);
+ query.bindValue(":sslverify", server.sslVerify);
}
net.useSasl = networksQuery.value(16).toBool();
net.saslAccount = networksQuery.value(17).toString();
net.saslPassword = networksQuery.value(18).toString();
+ // Custom rate limiting
+ net.useCustomMessageRate = networksQuery.value(19).toBool();
+ net.messageRateBurstSize = networksQuery.value(20).toUInt();
+ net.messageRateDelay = networksQuery.value(21).toUInt();
+ net.unlimitedMessageRate = networksQuery.value(22).toBool();
serversQuery.bindValue(":networkid", net.networkId.toInt());
safeExec(serversQuery);
server.proxyPort = serversQuery.value(8).toUInt();
server.proxyUser = serversQuery.value(9).toString();
server.proxyPass = serversQuery.value(10).toString();
+ server.sslVerify = serversQuery.value(11).toBool();
servers << server;
}
net.serverList = servers;
}
+void PostgreSqlStorage::setBufferActivity(UserId user, BufferId bufferId, Message::Types bufferActivity)
+{
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_buffer_bufferactivity"));
+
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":bufferid", bufferId.toInt());
+ query.bindValue(":bufferactivity", (int) bufferActivity);
+ safeExec(query);
+ watchQuery(query);
+}
+
+QHash<BufferId, Message::Types> PostgreSqlStorage::bufferActivities(UserId user)
+{
+ QHash<BufferId, Message::Types> bufferActivityHash;
+
+ QSqlDatabase db = logDb();
+ if (!beginReadOnlyTransaction(db)) {
+ qWarning() << "PostgreSqlStorage::bufferActivities(): cannot start read only transaction!";
+ qWarning() << " -" << qPrintable(db.lastError().text());
+ return bufferActivityHash;
+ }
+
+ QSqlQuery query(db);
+ query.prepare(queryString("select_buffer_bufferactivities"));
+ query.bindValue(":userid", user.toInt());
+ safeExec(query);
+ if (!watchQuery(query)) {
+ db.rollback();
+ return bufferActivityHash;
+ }
+
+ while (query.next()) {
+ bufferActivityHash[query.value(0).toInt()] = Message::Types(query.value(1).toInt());
+ }
+
+ db.commit();
+ return bufferActivityHash;
+}
+
+Message::Types PostgreSqlStorage::bufferActivity(BufferId bufferId, MsgId lastSeenMsgId)
+{
+ QSqlQuery query(logDb());
+ query.prepare(queryString("select_buffer_bufferactivity"));
+ query.bindValue(":bufferid", bufferId.toInt());
+ query.bindValue(":lastseenmsgid", lastSeenMsgId.toInt());
+ safeExec(query);
+ watchQuery(query);
+ Message::Types result = Message::Types(0);
+ if (query.first())
+ result = Message::Types(query.value(0).toInt());
+ return result;
+}
+
bool PostgreSqlStorage::logMessage(Message &msg)
{
QSqlDatabase db = logDb();
<< msg.type()
<< (int)msg.flags()
<< senderId
+ << msg.senderPrefixes()
<< msg.contents();
QSqlQuery logMessageQuery = executePreparedQuery("insert_message", params, db);
<< msg.type()
<< (int)msg.flags()
<< senderIdList.at(i)
+ << msg.senderPrefixes()
<< msg.contents();
QSqlQuery logMessageQuery = executePreparedQuery("insert_message", params, db);
if (!watchQuery(logMessageQuery)) {
QString queryName;
QVariantList params;
if (last == -1 && first == -1) {
- queryName = "select_messages";
+ queryName = "select_messagesNewestK";
}
else if (last == -1) {
queryName = "select_messagesNewerThan";
Message msg(timestamp,
bufferInfo,
(Message::Type)query.value(2).toUInt(),
- query.value(5).toString(),
+ query.value(6).toString(),
query.value(4).toString(),
+ query.value(5).toString(),
(Message::Flags)query.value(3).toUInt());
msg.setMsgId(query.value(0).toInt());
messagelist << msg;
Message msg(timestamp,
bufferInfoHash[query.value(1).toInt()],
(Message::Type)query.value(3).toUInt(),
- query.value(6).toString(),
+ query.value(7).toString(),
query.value(5).toString(),
+ query.value(6).toString(),
(Message::Flags)query.value(4).toUInt());
msg.setMsgId(query.value(0).toInt());
messagelist << msg;
bindValue(0, user.id.toInt());
bindValue(1, user.username);
bindValue(2, user.password);
+ bindValue(3, user.hashversion);
+ bindValue(4, user.authenticator);
return exec();
}
bindValue(22, network.usesasl);
bindValue(23, network.saslaccount);
bindValue(24, network.saslpassword);
+ // Custom rate limiting
+ bindValue(25, network.usecustommessagerate);
+ bindValue(26, network.messagerateburstsize);
+ bindValue(27, network.messageratedelay);
+ bindValue(28, network.unlimitedmessagerate);
return exec();
}
bindValue(4, buffer.buffername);
bindValue(5, buffer.buffercname);
bindValue(6, (int)buffer.buffertype);
- bindValue(7, buffer.lastseenmsgid);
- bindValue(8, buffer.markerlinemsgid);
- bindValue(9, buffer.key);
- bindValue(10, buffer.joined);
+ bindValue(7, buffer.lastmsgid);
+ bindValue(8, buffer.lastseenmsgid);
+ bindValue(9, buffer.markerlinemsgid);
+ bindValue(10, buffer.bufferactivity);
+ bindValue(11, buffer.key);
+ bindValue(12, buffer.joined);
return exec();
}
bindValue(3, backlog.type);
bindValue(4, (int)backlog.flags);
bindValue(5, backlog.senderid);
- bindValue(6, backlog.message);
+ bindValue(6, backlog.senderprefixes);
+ bindValue(7, backlog.message);
return exec();
}
bindValue(11, ircserver.proxyport);
bindValue(12, ircserver.proxyuser);
bindValue(13, ircserver.proxypass);
+ bindValue(14, ircserver.sslverify);
return exec();
}
if (!exec())
return false;
}
+
+ // Update the lastmsgid for all existing buffers.
+ resetQuery();
+ newQuery(QString("SELECT populate_lastmsgid()"), db);
+ if (!exec())
+ return false;
return true;
}