forked from qt-creator/qt-creator
Lua: Ask user before allowing to fetch
Change-Id: I58318598015a24689de19ae00bce65f004091e6b Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -42,6 +42,12 @@ add_qtc_plugin(Lua
|
||||
# generateqtbindings.cpp # Use this if you need to generate some code.
|
||||
)
|
||||
|
||||
qt_add_resources(Lua lua_images_rcc
|
||||
PREFIX "/lua"
|
||||
FILES
|
||||
images/settingscategory_lua.png
|
||||
images/settingscategory_lua@2x.png
|
||||
)
|
||||
|
||||
set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON)
|
||||
|
||||
|
@@ -3,11 +3,22 @@
|
||||
|
||||
#include "../luaengine.h"
|
||||
#include "../luaqttypes.h"
|
||||
#include "../luatr.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <utils/aspects.h>
|
||||
#include <utils/infobar.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
#include <utils/networkaccessmanager.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaEnum>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
@@ -37,8 +48,91 @@ static QString opToString(QNetworkAccessManager::Operation op)
|
||||
|
||||
void addFetchModule()
|
||||
{
|
||||
LuaEngine::registerProvider(
|
||||
"Fetch", [](sol::state_view lua) -> sol::object {
|
||||
class Module : Utils::AspectContainer
|
||||
{
|
||||
Utils::StringListAspect pluginsAllowedToFetch{this};
|
||||
Utils::StringListAspect pluginsNotAllowedToFetch{this};
|
||||
|
||||
class LuaOptionsPage : public Core::IOptionsPage
|
||||
{
|
||||
public:
|
||||
LuaOptionsPage(Module *module)
|
||||
{
|
||||
setId("BB.Lua.Fetch");
|
||||
setDisplayName(Tr::tr("Network access"));
|
||||
setCategory("ZY.Lua");
|
||||
setDisplayCategory("Lua");
|
||||
setCategoryIconPath(":/lua/images/settingscategory_lua.png");
|
||||
setSettingsProvider(
|
||||
[module] { return static_cast<Utils::AspectContainer *>(module); });
|
||||
}
|
||||
};
|
||||
|
||||
LuaOptionsPage settingsPage{this};
|
||||
|
||||
public:
|
||||
Module()
|
||||
{
|
||||
setSettingsGroup("Lua.Fetch");
|
||||
|
||||
pluginsAllowedToFetch.setSettingsKey("pluginsAllowedToFetch");
|
||||
pluginsAllowedToFetch.setLabelText("Plugins allowed to fetch data from the internet");
|
||||
pluginsAllowedToFetch.setToolTip(
|
||||
"List of plugins that are allowed to fetch data from the internet");
|
||||
pluginsAllowedToFetch.setUiAllowAdding(false);
|
||||
pluginsAllowedToFetch.setUiAllowEditing(false);
|
||||
|
||||
pluginsNotAllowedToFetch.setSettingsKey("pluginsNotAllowedToFetch");
|
||||
pluginsNotAllowedToFetch.setLabelText(
|
||||
"Plugins not allowed to fetch data from the internet");
|
||||
pluginsNotAllowedToFetch.setToolTip(
|
||||
"List of plugins that are not allowed to fetch data from the internet");
|
||||
pluginsNotAllowedToFetch.setUiAllowAdding(false);
|
||||
pluginsNotAllowedToFetch.setUiAllowEditing(false);
|
||||
|
||||
setLayouter([this] {
|
||||
using namespace Layouting;
|
||||
// clang-format off
|
||||
return Form {
|
||||
pluginsAllowedToFetch, br,
|
||||
pluginsNotAllowedToFetch, br,
|
||||
};
|
||||
// clang-format on
|
||||
});
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
||||
~Module() { writeSettings(); }
|
||||
|
||||
enum class IsAllowed { Yes, No, NeedsToAsk };
|
||||
|
||||
IsAllowed isAllowedToFetch(const QString &pluginName) const
|
||||
{
|
||||
if (pluginsAllowedToFetch().contains(pluginName))
|
||||
return IsAllowed::Yes;
|
||||
if (pluginsNotAllowedToFetch().contains(pluginName))
|
||||
return IsAllowed::No;
|
||||
return IsAllowed::NeedsToAsk;
|
||||
}
|
||||
|
||||
void setAllowedToFetch(const QString &pluginName, IsAllowed allowed)
|
||||
{
|
||||
if (allowed == IsAllowed::Yes)
|
||||
pluginsAllowedToFetch.appendValue(pluginName);
|
||||
else if (allowed == IsAllowed::No)
|
||||
pluginsNotAllowedToFetch.appendValue(pluginName);
|
||||
|
||||
if (allowed == IsAllowed::Yes)
|
||||
pluginsNotAllowedToFetch.removeValue(pluginName);
|
||||
else if (allowed == IsAllowed::No)
|
||||
pluginsAllowedToFetch.removeValue(pluginName);
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<Module> module = std::make_shared<Module>();
|
||||
|
||||
LuaEngine::registerProvider("Fetch", [mod = std::move(module)](sol::state_view lua) -> sol::object {
|
||||
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
|
||||
|
||||
sol::table async = lua.script("return require('async')", "_fetch_").get<sol::table>();
|
||||
@@ -60,12 +154,99 @@ void addFetchModule()
|
||||
.arg(r->error());
|
||||
});
|
||||
|
||||
fetch["fetch_cb"] = [guard = pluginSpec->connectionGuard.get()](
|
||||
auto checkPermission = [mod,
|
||||
pluginName = pluginSpec->name,
|
||||
guard = pluginSpec->connectionGuard.get()](
|
||||
QString url,
|
||||
std::function<void()> fetch,
|
||||
std::function<void()> notAllowed) {
|
||||
auto isAllowed = mod->isAllowedToFetch(pluginName);
|
||||
if (isAllowed == Module::IsAllowed::Yes) {
|
||||
fetch();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAllowed == Module::IsAllowed::No) {
|
||||
notAllowed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QApplication::activeModalWidget()) {
|
||||
// We are already showing a modal dialog,
|
||||
// so we have to use a QMessageBox instead of the info bar
|
||||
auto msgBox = new QMessageBox(
|
||||
QMessageBox::Question,
|
||||
Tr::tr("Allow Internet access"),
|
||||
Tr::tr("The plugin \"%1\" would like to fetch from the following url:\n%2")
|
||||
.arg(pluginName)
|
||||
.arg(url),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
Core::ICore::dialogParent());
|
||||
msgBox->setCheckBox(new QCheckBox(Tr::tr("Remember choice")));
|
||||
|
||||
QObject::connect(
|
||||
msgBox, &QMessageBox::accepted, guard, [mod, fetch, pluginName, msgBox]() {
|
||||
if (msgBox->checkBox()->isChecked())
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
|
||||
fetch();
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
msgBox, &QMessageBox::rejected, guard, [mod, notAllowed, pluginName, msgBox]() {
|
||||
if (msgBox->checkBox()->isChecked())
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
|
||||
notAllowed();
|
||||
});
|
||||
|
||||
msgBox->show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::InfoBarEntry entry{
|
||||
Utils::Id::fromString("Fetch" + pluginName),
|
||||
Tr::tr("The plugin \"%1\" would like to fetch data from the internet. Do "
|
||||
"you want to allow this?")
|
||||
.arg(pluginName)};
|
||||
entry.setDetailsWidgetCreator([pluginName, url] {
|
||||
const QString markdown = Tr::tr("The plugin \"**%1**\" would like to fetch "
|
||||
"from the following url:\n\n")
|
||||
.arg(pluginName)
|
||||
+ QString("* [%3](%3)").arg(url);
|
||||
|
||||
QLabel *list = new QLabel();
|
||||
list->setTextFormat(Qt::TextFormat::MarkdownText);
|
||||
list->setText(markdown);
|
||||
list->setMargin(Utils::StyleHelper::SpacingTokens::ExPaddingGapS);
|
||||
return list;
|
||||
});
|
||||
entry.addCustomButton(Tr::tr("Always Allow"), [mod, pluginName, fetch]() {
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::Yes);
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
fetch();
|
||||
});
|
||||
entry.addCustomButton(Tr::tr("Allow once"), [pluginName, fetch]() {
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
fetch();
|
||||
});
|
||||
|
||||
entry.setCancelButtonInfo(Tr::tr("Deny"), [mod, notAllowed, pluginName]() {
|
||||
Core::ICore::infoBar()->removeInfo(Utils::Id::fromString("Fetch" + pluginName));
|
||||
mod->setAllowedToFetch(pluginName, Module::IsAllowed::No);
|
||||
notAllowed();
|
||||
});
|
||||
Core::ICore::infoBar()->addInfo(entry);
|
||||
};
|
||||
|
||||
fetch["fetch_cb"] = [checkPermission,
|
||||
pluginName = pluginSpec->name,
|
||||
guard = pluginSpec->connectionGuard.get(),
|
||||
mod](
|
||||
const sol::table &options,
|
||||
const sol::function &callback,
|
||||
const sol::this_state &thisState) {
|
||||
auto url = options.get<QString>("url");
|
||||
|
||||
auto actualFetch = [guard, url, options, callback, thisState]() {
|
||||
auto method = (options.get_or<QString>("method", "GET")).toLower();
|
||||
auto headers = options.get_or<sol::table>("headers", {});
|
||||
auto data = options.get_or<QString>("body", {});
|
||||
@@ -129,6 +310,13 @@ void addFetchModule()
|
||||
}
|
||||
};
|
||||
|
||||
checkPermission(url, actualFetch, [callback, pluginName]() {
|
||||
callback(Tr::tr("Fetching is not allowed for the plugin \"%1\" (You can edit "
|
||||
"permissions in Preferences => Lua)")
|
||||
.arg(pluginName));
|
||||
});
|
||||
};
|
||||
|
||||
fetch["fetch"] = wrap(fetch["fetch_cb"]);
|
||||
|
||||
return fetch;
|
||||
|
BIN
src/plugins/lua/images/settingscategory_lua.png
Normal file
BIN
src/plugins/lua/images/settingscategory_lua.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 513 B |
BIN
src/plugins/lua/images/settingscategory_lua@2x.png
Normal file
BIN
src/plugins/lua/images/settingscategory_lua@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user