mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
added insecure credential store
This commit is contained in:
parent
eadf5355ee
commit
7c6f744e73
8 changed files with 118 additions and 74 deletions
|
@ -179,7 +179,6 @@ SOURCES += \
|
|||
src/widgets/AttachedWindow.cpp \
|
||||
src/widgets/dialogs/EmotePopup.cpp \
|
||||
src/widgets/dialogs/IrcConnectionEditor.cpp \
|
||||
src/widgets/dialogs/IrcConnectionPopup.cpp \
|
||||
src/widgets/dialogs/LastRunCrashDialog.cpp \
|
||||
src/widgets/dialogs/LoginDialog.cpp \
|
||||
src/widgets/dialogs/LogsPopup.cpp \
|
||||
|
@ -360,7 +359,6 @@ HEADERS += \
|
|||
src/widgets/AttachedWindow.hpp \
|
||||
src/widgets/dialogs/EmotePopup.hpp \
|
||||
src/widgets/dialogs/IrcConnectionEditor.hpp \
|
||||
src/widgets/dialogs/IrcConnectionPopup.hpp \
|
||||
src/widgets/dialogs/LastRunCrashDialog.hpp \
|
||||
src/widgets/dialogs/LoginDialog.hpp \
|
||||
src/widgets/dialogs/LogsPopup.hpp \
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include "keychain.h"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/CombinePath.hpp"
|
||||
|
||||
#include <QSaveFile>
|
||||
|
||||
#define FORMAT_NAME \
|
||||
([&] { \
|
||||
|
@ -11,6 +15,65 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
namespace {
|
||||
bool useKeyring()
|
||||
{
|
||||
if (getPaths()->isPortable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
return getSettings()->useKeyring;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Insecure storage:
|
||||
QString insecurePath()
|
||||
{
|
||||
return combinePath(getPaths()->settingsDirectory, "credentials.json");
|
||||
}
|
||||
|
||||
QJsonDocument loadInsecure()
|
||||
{
|
||||
QFile file(insecurePath());
|
||||
file.open(QIODevice::ReadOnly);
|
||||
return QJsonDocument::fromJson(file.readAll());
|
||||
}
|
||||
|
||||
void storeInsecure(const QJsonDocument &doc)
|
||||
{
|
||||
QSaveFile file(insecurePath());
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(doc.toJson());
|
||||
file.commit();
|
||||
}
|
||||
|
||||
QJsonDocument &insecureInstance()
|
||||
{
|
||||
static auto store = loadInsecure();
|
||||
return store;
|
||||
}
|
||||
|
||||
void queueInsecureSave()
|
||||
{
|
||||
static bool isQueued = false;
|
||||
|
||||
if (!isQueued)
|
||||
{
|
||||
isQueued = true;
|
||||
QTimer::singleShot(200, qApp, [] {
|
||||
storeInsecure(insecureInstance());
|
||||
isQueued = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Credentials &Credentials::getInstance()
|
||||
{
|
||||
static Credentials creds;
|
||||
|
@ -24,15 +87,11 @@ Credentials::Credentials()
|
|||
QString Credentials::get(const QString &provider, const QString &name_,
|
||||
std::function<void(QString)> &&onLoaded)
|
||||
{
|
||||
assertInGuiThread();
|
||||
|
||||
auto name = FORMAT_NAME;
|
||||
|
||||
if (getPaths()->isPortable())
|
||||
{
|
||||
assert(false);
|
||||
|
||||
return {};
|
||||
}
|
||||
else
|
||||
if (useKeyring())
|
||||
{
|
||||
auto job = new QKeychain::ReadPasswordJob("chatterino");
|
||||
job->setAutoDelete(true);
|
||||
|
@ -45,44 +104,69 @@ QString Credentials::get(const QString &provider, const QString &name_,
|
|||
|
||||
return job->textData();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &instance = insecureInstance();
|
||||
|
||||
return instance.object().find(name).value().toString();
|
||||
}
|
||||
}
|
||||
|
||||
void Credentials::set(const QString &provider, const QString &name_,
|
||||
const QString &credential)
|
||||
{
|
||||
assertInGuiThread();
|
||||
|
||||
/// On linux, we try to use a keychain but show a message to disable it when it fails.
|
||||
/// XXX: add said message
|
||||
|
||||
auto name = FORMAT_NAME;
|
||||
|
||||
if (getPaths()->isPortable())
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
if (useKeyring())
|
||||
{
|
||||
auto job = new QKeychain::WritePasswordJob("chatterino");
|
||||
job->setAutoDelete(true);
|
||||
job->setKey(name);
|
||||
job->setTextData(credential);
|
||||
QObject::connect(job, &QKeychain::Job::finished, qApp, [](auto) {});
|
||||
//QObject::connect(job, &QKeychain::Job::finished, qApp, [](auto) {});
|
||||
job->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &instance = insecureInstance();
|
||||
|
||||
instance.object()[name] = credential;
|
||||
|
||||
queueInsecureSave();
|
||||
}
|
||||
}
|
||||
|
||||
void Credentials::erase(const QString &provider, const QString &name_)
|
||||
{
|
||||
assertInGuiThread();
|
||||
|
||||
auto name = FORMAT_NAME;
|
||||
|
||||
if (getPaths()->isPortable())
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
if (useKeyring())
|
||||
{
|
||||
auto job = new QKeychain::DeletePasswordJob("chatterino");
|
||||
job->setAutoDelete(true);
|
||||
job->setKey(name);
|
||||
QObject::connect(job, &QKeychain::Job::finished, qApp, [](auto) {});
|
||||
//QObject::connect(job, &QKeychain::Job::finished, qApp, [](auto) {});
|
||||
job->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &instance = insecureInstance();
|
||||
|
||||
if (auto it = instance.object().find(name);
|
||||
it != instance.object().end())
|
||||
{
|
||||
instance.object().erase(it);
|
||||
}
|
||||
|
||||
queueInsecureSave();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -199,6 +199,10 @@ public:
|
|||
|
||||
/// Misc
|
||||
BoolSetting betaUpdates = {"/misc/beta", false};
|
||||
#ifdef Q_OS_LINUX
|
||||
BoolSetting useKeyring = {"/misc/useKeyring", true};
|
||||
#endif
|
||||
|
||||
IntSetting startUpNotification = {"/misc/startUpNotification", 0};
|
||||
QStringSetting currentVersion = {"/misc/currentVersion", ""};
|
||||
BoolSetting loadTwitchMessageHistoryOnConnect = {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "widgets/Window.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "common/Credentials.hpp"
|
||||
#include "common/Version.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "providers/twitch/TwitchServer.hpp"
|
||||
|
@ -103,7 +104,7 @@ bool Window::event(QEvent *event)
|
|||
break;
|
||||
|
||||
default:;
|
||||
};
|
||||
}
|
||||
|
||||
return BaseWindow::event(event);
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
#include "IrcConnectionPopup.hpp"
|
||||
|
||||
#include "providers/irc/Irc2.hpp"
|
||||
#include "util/LayoutHelper.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QTableView>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
IrcConnectionPopup::IrcConnectionPopup(QWidget *parent)
|
||||
: BaseWindow(parent, BaseWindow::Flags::EnableCustomFrame)
|
||||
{
|
||||
this->setWindowTitle("Edit Irc Connections");
|
||||
|
||||
// view
|
||||
auto view =
|
||||
new EditableModelView(Irc::getInstance().newConnectionModel(this));
|
||||
|
||||
view->setTitles({"host", "port", "ssl", "user", "nick", "password"});
|
||||
view->getTableView()->horizontalHeader()->resizeSection(0, 140);
|
||||
view->getTableView()->horizontalHeader()->resizeSection(1, 30);
|
||||
view->getTableView()->horizontalHeader()->resizeSection(2, 30);
|
||||
|
||||
this->setScaleIndependantSize(800, 500);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
auto unique = IrcServerData{};
|
||||
unique.id = Irc::getInstance().uniqueId();
|
||||
Irc::getInstance().connections.appendItem(unique);
|
||||
});
|
||||
|
||||
// init layout
|
||||
this->getLayoutContainer()->setLayout(makeLayout<QHBoxLayout>({view}));
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
|
@ -1,13 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class IrcConnectionPopup : public BaseWindow
|
||||
{
|
||||
public:
|
||||
IrcConnectionPopup(QWidget *parent);
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
|
@ -6,7 +6,6 @@
|
|||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/Notebook.hpp"
|
||||
#include "widgets/dialogs/IrcConnectionEditor.hpp"
|
||||
#include "widgets/dialogs/IrcConnectionPopup.hpp"
|
||||
#include "widgets/helper/NotebookTab.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
|
|
|
@ -377,6 +377,15 @@ void GeneralPage::initLayout(SettingsLayout &layout)
|
|||
|
||||
layout.addTitle("Miscellaneous");
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!getPaths()->isPortable())
|
||||
{
|
||||
layout.addCheckbox(
|
||||
"Use libsecret/KWallet/Gnome keychain to secure passwords",
|
||||
s.useKeyring);
|
||||
}
|
||||
#endif
|
||||
|
||||
layout.addCheckbox("Show moderation messages", s.hideModerationActions,
|
||||
true);
|
||||
layout.addCheckbox("Random username color for users who never set a color",
|
||||
|
|
Loading…
Reference in a new issue