credentials are now loaded when needed

This commit is contained in:
fourtf 2019-09-14 20:45:01 +02:00
parent d33a8b1b3a
commit 13d1fab303
15 changed files with 100 additions and 63 deletions

View file

@ -79,6 +79,8 @@ void Application::initialize(Settings &settings, Paths &paths)
assert(isAppInitialized == false);
isAppInitialized = true;
Irc::getInstance().load();
for (auto &singleton : this->singletons_)
{
singleton->initialize(settings, paths);
@ -98,7 +100,6 @@ int Application::run(QApplication &qtApp)
assert(isAppInitialized);
this->twitch.server->connect();
Irc::getInstance().load();
this->windows->getMainWindow().show();

View file

@ -86,6 +86,7 @@ Credentials::Credentials()
}
void Credentials::get(const QString &provider, const QString &name_,
QObject *receiver,
std::function<void(const QString &)> &&onLoaded)
{
assertInGuiThread();
@ -97,7 +98,7 @@ void Credentials::get(const QString &provider, const QString &name_,
auto job = new QKeychain::ReadPasswordJob("chatterino");
job->setAutoDelete(true);
job->setKey(name);
QObject::connect(job, &QKeychain::Job::finished, qApp,
QObject::connect(job, &QKeychain::Job::finished, receiver,
[job, onLoaded = std::move(onLoaded)](auto) mutable {
onLoaded(job->textData());
},

View file

@ -10,7 +10,7 @@ class Credentials
public:
static Credentials &getInstance();
void get(const QString &provider, const QString &name,
void get(const QString &provider, const QString &name, QObject *receiver,
std::function<void(const QString &)> &&onLoaded);
void set(const QString &provider, const QString &name,
const QString &credential);

View file

@ -78,19 +78,26 @@ void AbstractIrcServer::connect()
if (this->hasSeparateWriteConnection())
{
this->initializeConnection(this->writeConnection_.get(), false, true);
this->initializeConnection(this->readConnection_.get(), true, false);
this->initializeConnection(this->writeConnection_.get(), Write);
this->initializeConnection(this->readConnection_.get(), Read);
}
else
{
this->initializeConnection(this->readConnection_.get(), true, true);
this->initializeConnection(this->readConnection_.get(), Both);
}
}
// fourtf: this should be asynchronous
void AbstractIrcServer::open(ConnectionType type)
{
std::lock_guard<std::mutex> lock1(this->connectionMutex_);
std::lock_guard<std::mutex> lock2(this->channelMutex);
if (type == Write)
{
this->writeConnection_->open();
}
if (type & Read)
{
std::lock_guard<std::mutex> lock1(this->connectionMutex_);
std::lock_guard<std::mutex> lock2(this->channelMutex);
for (std::weak_ptr<Channel> &weak : this->channels.values())
{
if (auto channel = weak.lock())
@ -98,11 +105,6 @@ void AbstractIrcServer::connect()
this->readConnection_->sendRaw("JOIN #" + channel->getName());
}
}
if (this->hasSeparateWriteConnection())
{
this->writeConnection_->open();
}
this->readConnection_->open();
}
}
@ -254,6 +256,16 @@ void AbstractIrcServer::onReadConnected(IrcConnection *connection)
std::lock_guard lock(this->channelMutex);
// join channels
for (auto &&weak : this->channels)
{
if (auto channel = weak.lock())
{
connection->sendRaw("JOIN #" + channel->getName());
}
}
// connected/disconnected message
auto connectedMsg = makeSystemMessage("connected");
connectedMsg->flags.set(MessageFlag::ConnectedMessage);
auto reconnected = makeSystemMessage("reconnected");

View file

@ -17,6 +17,8 @@ using ChannelPtr = std::shared_ptr<Channel>;
class AbstractIrcServer : public QObject
{
public:
enum ConnectionType { Read = 1, Write = 2, Both = 3 };
virtual ~AbstractIrcServer() = default;
// connection
@ -43,8 +45,8 @@ public:
protected:
AbstractIrcServer();
virtual void initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite) = 0;
virtual void initializeConnection(IrcConnection *connection,
ConnectionType type) = 0;
virtual std::shared_ptr<Channel> createChannel(
const QString &channelName) = 0;
@ -63,6 +65,8 @@ protected:
virtual bool hasSeparateWriteConnection() const = 0;
virtual QString cleanChannelName(const QString &dirtyChannelName);
void open(ConnectionType type);
QMap<QString, std::weak_ptr<Channel>> channels;
std::mutex channelMutex;

View file

@ -38,7 +38,6 @@ namespace {
row[3]->data(Qt::EditRole).toString(), // user
row[4]->data(Qt::EditRole).toString(), // nick
row[5]->data(Qt::EditRole).toString(), // real
original.password, // password
original.connectCommands, // connectCommands
original.id, // id
};
@ -70,6 +69,18 @@ inline QString getCredentialName(const IrcServerData &data)
escape(data.host);
}
void IrcServerData::getPassword(
QObject *receiver, std::function<void(const QString &)> &&onLoaded) const
{
Credentials::getInstance().get("irc", getCredentialName(*this), receiver,
std::move(onLoaded));
}
void IrcServerData::setPassword(const QString &password)
{
Credentials::getInstance().set("irc", getCredentialName(*this), password);
}
Irc::Irc()
{
this->connections.itemInserted.connect([this](auto &&args) {
@ -99,10 +110,6 @@ Irc::Irc()
this->servers_.emplace(args.item.id,
std::make_unique<IrcServer>(args.item));
}
// store password
Credentials::getInstance().set("irc", getCredentialName(args.item),
args.item.password);
});
this->connections.itemRemoved.connect([this](auto &&args) {
@ -217,6 +224,8 @@ void Irc::load()
file.open(QIODevice::ReadOnly);
auto object = QJsonDocument::fromJson(file.readAll()).object();
std::unordered_set<int> ids;
// load servers
for (auto server : object.value("servers").toArray())
{
@ -233,18 +242,11 @@ void Irc::load()
data.id = obj.value("id").toInt(data.id);
// duplicate id's are not allowed :(
if (this->abandonedChannels_.find(data.id) ==
this->abandonedChannels_.end())
if (ids.find(data.id) == ids.end())
{
// insert element
this->abandonedChannels_[data.id];
ids.insert(data.id);
Credentials::getInstance().get(
"irc", getCredentialName(data),
[=](const QString &password) mutable {
data.password = password;
this->connections.appendItem(data);
});
this->connections.appendItem(data);
}
}
}

View file

@ -22,7 +22,10 @@ struct IrcServerData {
QString real;
// IrcAuthType authType = Anonymous;
QString password;
void getPassword(QObject *receiver,
std::function<void(const QString &)> &&onLoaded) const;
void setPassword(const QString &password);
QStringList connectCommands;
int id;

View file

@ -20,6 +20,7 @@ void IrcChannel::sendMessage(const QString &message)
this->server()->sendMessage(this->getName(), message);
MessageBuilder builder;
builder.emplace<TimestampElement>();
builder.emplace<TextElement>(this->server()->nick() + ":",
MessageElementFlag::Username);
builder.emplace<TextElement>(message, MessageElementFlag::Text);

View file

@ -5,6 +5,7 @@
#include "messages/MessageBuilder.hpp"
#include "providers/irc/Irc2.hpp"
#include "providers/irc/IrcChannel2.hpp"
#include "util/QObjectRef.hpp"
namespace chatterino {
@ -44,13 +45,13 @@ const QString &IrcServer::user()
const QString &IrcServer::nick()
{
return this->data_->nick;
return this->data_->nick.isEmpty() ? this->data_->user : this->data_->nick;
}
void IrcServer::initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite)
void IrcServer::initializeConnection(IrcConnection *connection,
ConnectionType type)
{
assert(isRead && isWrite);
assert(type == Both);
connection->setSecure(this->data_->ssl);
connection->setHost(this->data_->host);
@ -61,7 +62,18 @@ void IrcServer::initializeConnection(IrcConnection *connection, bool isRead,
: this->data_->nick);
connection->setRealName(this->data_->real.isEmpty() ? this->data_->user
: this->data_->nick);
connection->setPassword(this->data_->password);
this->data_->getPassword(
this, [conn = new QObjectRef(connection) /* can't copy */,
this](const QString &password) mutable {
if (*conn)
{
(*conn)->setPassword(password);
this->open(Both);
}
delete conn;
});
}
std::shared_ptr<Channel> IrcServer::createChannel(const QString &channelName)
@ -76,22 +88,16 @@ bool IrcServer::hasSeparateWriteConnection() const
void IrcServer::onReadConnected(IrcConnection *connection)
{
AbstractIrcServer::onReadConnected(connection);
std::lock_guard lock(this->channelMutex);
for (auto &&command : this->data_->connectCommands)
{
connection->sendRaw(command + "\r\n");
}
std::lock_guard lock(this->channelMutex);
for (auto &&weak : this->channels)
{
if (auto channel = weak.lock())
for (auto &&command : this->data_->connectCommands)
{
connection->sendRaw("JOIN #" + channel->getName());
connection->sendRaw(command + "\r\n");
}
}
AbstractIrcServer::onReadConnected(connection);
}
void IrcServer::privateMessageReceived(Communi::IrcPrivateMessage *message)

View file

@ -21,8 +21,8 @@ public:
// AbstractIrcServer interface
protected:
void initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite) override;
void initializeConnection(IrcConnection *connection,
ConnectionType type) override;
std::shared_ptr<Channel> createChannel(const QString &channelName) override;
bool hasSeparateWriteConnection() const override;

View file

@ -63,11 +63,9 @@ void TwitchServer::initialize(Settings &settings, Paths &paths)
this->ffz.loadEmotes();
}
void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite)
void TwitchServer::initializeConnection(IrcConnection *connection,
ConnectionType type)
{
this->singleConnection_ = isRead == isWrite;
std::shared_ptr<TwitchAccount> account =
getApp()->accounts->twitch.getCurrent();
@ -97,6 +95,8 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,
// SSL enabled: irc://irc.chat.twitch.tv:6697
connection->setHost("irc.chat.twitch.tv");
connection->setPort(6697);
this->open(type);
}
std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)

View file

@ -44,8 +44,8 @@ public:
const FfzEmotes &getFfzEmotes() const;
protected:
virtual void initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite) override;
virtual void initializeConnection(IrcConnection *connection,
ConnectionType type) override;
virtual std::shared_ptr<Channel> createChannel(
const QString &channelName) override;
@ -75,7 +75,6 @@ private:
std::chrono::steady_clock::time_point lastErrorTimeSpeed_;
std::chrono::steady_clock::time_point lastErrorTimeAmount_;
bool singleConnection_ = false;
TwitchBadges twitchBadges;
BttvEmotes bttv;
FfzEmotes ffz;

View file

@ -62,8 +62,9 @@ private:
if (other)
{
this->conn_ =
QObject::connect(other, &QObject::destroyed,
[this](QObject *) { this->set(nullptr); });
QObject::connect(other, &QObject::destroyed, qApp,
[this](QObject *) { this->set(nullptr); },
Qt::DirectConnection);
}
this->t_ = other;

View file

@ -28,7 +28,10 @@ IrcConnectionEditor::IrcConnectionEditor(const IrcServerData &data, bool isAdd,
this->ui_->realNameLineEdit->setText(data.real);
this->ui_->connectCommandsEditor->setPlainText(
data.connectCommands.join('\n'));
this->ui_->passwordLineEdit->setText(data.password);
data.getPassword(this, [this](const QString &password) {
this->ui_->passwordLineEdit->setText(password);
});
QFont font("Monospace");
font.setStyleHint(QFont::TypeWriter);
@ -51,7 +54,7 @@ IrcServerData IrcConnectionEditor::data()
data.real = this->ui_->realNameLineEdit->text();
data.connectCommands =
this->ui_->connectCommandsEditor->toPlainText().split('\n');
data.password = this->ui_->passwordLineEdit->text();
data.setPassword(this->ui_->passwordLineEdit->text());
return data;
}

View file

@ -158,7 +158,11 @@
<item row="10" column="0">
<widget class="QLabel" name="connectCommandsLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send IRC commands&lt;/p&gt;&lt;p&gt;on connect:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Send IRC commands
on connect:</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
</widget>
</item>