mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-10 00:46:48 -06:00
parent
9ce5463d9d
commit
a8e9e800b3
@ -3,6 +3,8 @@
|
|||||||
## 2.14.1
|
## 2.14.1
|
||||||
* [#23212](https://github.com/qbittorrent/qBittorrent/pull/23212)
|
* [#23212](https://github.com/qbittorrent/qBittorrent/pull/23212)
|
||||||
* Add `app/rotateAPIKey` endpoint for generating, and rotating, the WebAPI API key
|
* Add `app/rotateAPIKey` endpoint for generating, and rotating, the WebAPI API key
|
||||||
|
* [#23388](https://github.com/qbittorrent/qBittorrent/pull/23388)
|
||||||
|
* Add `app/deleteAPIKey` endpoint for deleting the existing WebAPI API key
|
||||||
|
|
||||||
## 2.14.0
|
## 2.14.0
|
||||||
* [#23202](https://github.com/qbittorrent/qBittorrent/pull/23202)
|
* [#23202](https://github.com/qbittorrent/qBittorrent/pull/23202)
|
||||||
|
|||||||
@ -1356,21 +1356,10 @@ void OptionsDialog::loadWebUITabOptions()
|
|||||||
|
|
||||||
// API Key
|
// API Key
|
||||||
if (const QString apiKey = pref->getWebUIApiKey(); Utils::APIKey::isValid(apiKey))
|
if (const QString apiKey = pref->getWebUIApiKey(); Utils::APIKey::isValid(apiKey))
|
||||||
{
|
|
||||||
m_currentAPIKey = apiKey;
|
m_currentAPIKey = apiKey;
|
||||||
m_ui->textWebUIAPIKey->setText(maskAPIKey(m_currentAPIKey));
|
|
||||||
m_ui->textWebUIAPIKey->setEnabled(true);
|
|
||||||
m_ui->btnWebUIAPIKeyCopy->setEnabled(true);
|
|
||||||
m_ui->btnWebUIAPIKeyRotate->setToolTip(tr("Rotate API key"));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_currentAPIKey.clear();
|
m_currentAPIKey.clear();
|
||||||
m_ui->textWebUIAPIKey->clear();
|
setupWebUIAPIKey();
|
||||||
m_ui->textWebUIAPIKey->setEnabled(false);
|
|
||||||
m_ui->btnWebUIAPIKeyCopy->setEnabled(false);
|
|
||||||
m_ui->btnWebUIAPIKeyRotate->setToolTip(tr("Generate API key"));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUILocalAuthEnabled());
|
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUILocalAuthEnabled());
|
||||||
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUIAuthSubnetWhitelistEnabled());
|
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUIAuthSubnetWhitelistEnabled());
|
||||||
@ -1412,8 +1401,9 @@ void OptionsDialog::loadWebUITabOptions()
|
|||||||
|
|
||||||
connect(m_ui->textWebUIUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->textWebUIUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->textWebUIPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
connect(m_ui->textWebUIPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->btnWebUIAPIKeyCopy, &QPushButton::clicked, this, &ThisType::onBtnWebUIAPIKeyCopy);
|
connect(m_ui->btnWebUIAPIKeyCopy, &QPushButton::clicked, this, &ThisType::onBtnWebUIAPIKeyCopyClicked);
|
||||||
connect(m_ui->btnWebUIAPIKeyRotate, &QPushButton::clicked, this, &ThisType::onBtnWebUIAPIKeyRotate);
|
connect(m_ui->btnWebUIAPIKeyRotate, &QPushButton::clicked, this, &ThisType::onBtnWebUIAPIKeyRotateClicked);
|
||||||
|
connect(m_ui->btnWebUIAPIKeyDelete, &QPushButton::clicked, this, &ThisType::onBtnWebUIAPIKeyDeleteClicked);
|
||||||
|
|
||||||
connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
connect(m_ui->checkBypassAuthSubnetWhitelist, &QAbstractButton::toggled, this, &ThisType::enableApplyButton);
|
||||||
@ -1490,13 +1480,13 @@ void OptionsDialog::saveWebUITabOptions() const
|
|||||||
pref->setDynDNSPassword(m_ui->DNSPasswordTxt->text());
|
pref->setDynDNSPassword(m_ui->DNSPasswordTxt->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsDialog::onBtnWebUIAPIKeyCopy()
|
void OptionsDialog::onBtnWebUIAPIKeyCopyClicked()
|
||||||
{
|
{
|
||||||
if (!m_currentAPIKey.isEmpty())
|
if (!m_currentAPIKey.isEmpty())
|
||||||
QApplication::clipboard()->setText(m_currentAPIKey);
|
QApplication::clipboard()->setText(m_currentAPIKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionsDialog::onBtnWebUIAPIKeyRotate()
|
void OptionsDialog::onBtnWebUIAPIKeyRotateClicked()
|
||||||
{
|
{
|
||||||
const QString title = m_currentAPIKey.isEmpty()
|
const QString title = m_currentAPIKey.isEmpty()
|
||||||
? tr("Generate API key")
|
? tr("Generate API key")
|
||||||
@ -1511,16 +1501,51 @@ void OptionsDialog::onBtnWebUIAPIKeyRotate()
|
|||||||
if (button == QMessageBox::Yes)
|
if (button == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
m_currentAPIKey = Utils::APIKey::generate();
|
m_currentAPIKey = Utils::APIKey::generate();
|
||||||
m_ui->textWebUIAPIKey->setText(maskAPIKey(m_currentAPIKey));
|
setupWebUIAPIKey();
|
||||||
m_ui->textWebUIAPIKey->setEnabled(true);
|
|
||||||
m_ui->btnWebUIAPIKeyCopy->setEnabled(true);
|
|
||||||
m_ui->btnWebUIAPIKeyRotate->setToolTip(tr("Rotate API key"));
|
|
||||||
|
|
||||||
auto *preferences = Preferences::instance();
|
auto *preferences = Preferences::instance();
|
||||||
preferences->setWebUIApiKey(m_currentAPIKey);
|
preferences->setWebUIApiKey(m_currentAPIKey);
|
||||||
preferences->apply();
|
preferences->apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptionsDialog::onBtnWebUIAPIKeyDeleteClicked()
|
||||||
|
{
|
||||||
|
const QString title = tr("Delete API key");
|
||||||
|
const QString message = tr("Delete this API key? The current key will immediately stop working.");
|
||||||
|
const QMessageBox::StandardButton button = QMessageBox::question(
|
||||||
|
this, title, message, (QMessageBox::Yes | QMessageBox::No), QMessageBox::No);
|
||||||
|
|
||||||
|
if (button == QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
m_currentAPIKey.clear();
|
||||||
|
setupWebUIAPIKey();
|
||||||
|
|
||||||
|
auto *preferences = Preferences::instance();
|
||||||
|
preferences->setWebUIApiKey(m_currentAPIKey);
|
||||||
|
preferences->apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsDialog::setupWebUIAPIKey()
|
||||||
|
{
|
||||||
|
if (Utils::APIKey::isValid(m_currentAPIKey))
|
||||||
|
{
|
||||||
|
m_ui->textWebUIAPIKey->setText(maskAPIKey(m_currentAPIKey));
|
||||||
|
m_ui->textWebUIAPIKey->setEnabled(true);
|
||||||
|
m_ui->btnWebUIAPIKeyCopy->setEnabled(true);
|
||||||
|
m_ui->btnWebUIAPIKeyRotate->setToolTip(tr("Rotate API key"));
|
||||||
|
m_ui->btnWebUIAPIKeyDelete->setEnabled(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ui->textWebUIAPIKey->clear();
|
||||||
|
m_ui->textWebUIAPIKey->setEnabled(false);
|
||||||
|
m_ui->btnWebUIAPIKeyCopy->setEnabled(false);
|
||||||
|
m_ui->btnWebUIAPIKeyRotate->setToolTip(tr("Generate API key"));
|
||||||
|
m_ui->btnWebUIAPIKeyDelete->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // DISABLE_WEBUI
|
#endif // DISABLE_WEBUI
|
||||||
|
|
||||||
void OptionsDialog::initializeLanguageCombo()
|
void OptionsDialog::initializeLanguageCombo()
|
||||||
|
|||||||
@ -110,8 +110,10 @@ private slots:
|
|||||||
void webUIHttpsCertChanged(const Path &path);
|
void webUIHttpsCertChanged(const Path &path);
|
||||||
void webUIHttpsKeyChanged(const Path &path);
|
void webUIHttpsKeyChanged(const Path &path);
|
||||||
void on_registerDNSBtn_clicked();
|
void on_registerDNSBtn_clicked();
|
||||||
void onBtnWebUIAPIKeyCopy();
|
void onBtnWebUIAPIKeyCopyClicked();
|
||||||
void onBtnWebUIAPIKeyRotate();
|
void onBtnWebUIAPIKeyRotateClicked();
|
||||||
|
void onBtnWebUIAPIKeyDeleteClicked();
|
||||||
|
void setupWebUIAPIKey();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -3861,6 +3861,35 @@ Specify an IPv4 or IPv6 address. You can specify "0.0.0.0" for any IPv
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnWebUIAPIKeyDelete">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Delete API key</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/list-remove.svg</normaloff>:/icons/list-remove.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@ -1326,6 +1326,13 @@ void AppController::rotateAPIKeyAction()
|
|||||||
setResult(QJsonObject {{u"apiKey"_s, key}});
|
setResult(QJsonObject {{u"apiKey"_s, key}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppController::deleteAPIKeyAction()
|
||||||
|
{
|
||||||
|
auto *preferences = Preferences::instance();
|
||||||
|
preferences->setWebUIApiKey({});
|
||||||
|
preferences->apply();
|
||||||
|
}
|
||||||
|
|
||||||
void AppController::networkInterfaceListAction()
|
void AppController::networkInterfaceListAction()
|
||||||
{
|
{
|
||||||
QJsonArray ifaceList;
|
QJsonArray ifaceList;
|
||||||
|
|||||||
@ -53,6 +53,7 @@ private slots:
|
|||||||
void cookiesAction();
|
void cookiesAction();
|
||||||
void setCookiesAction();
|
void setCookiesAction();
|
||||||
void rotateAPIKeyAction();
|
void rotateAPIKeyAction();
|
||||||
|
void deleteAPIKeyAction();
|
||||||
|
|
||||||
void networkInterfaceListAction();
|
void networkInterfaceListAction();
|
||||||
void networkInterfaceAddressListAction();
|
void networkInterfaceAddressListAction();
|
||||||
|
|||||||
@ -53,7 +53,7 @@
|
|||||||
#include "base/utils/version.h"
|
#include "base/utils/version.h"
|
||||||
#include "api/isessionmanager.h"
|
#include "api/isessionmanager.h"
|
||||||
|
|
||||||
inline const Utils::Version<3, 2> API_VERSION {2, 14, 0};
|
inline const Utils::Version<3, 2> API_VERSION {2, 14, 1};
|
||||||
|
|
||||||
class APIController;
|
class APIController;
|
||||||
class AuthController;
|
class AuthController;
|
||||||
@ -150,6 +150,7 @@ private:
|
|||||||
const QHash<std::pair<QString, QString>, QString> m_allowedMethod =
|
const QHash<std::pair<QString, QString>, QString> m_allowedMethod =
|
||||||
{
|
{
|
||||||
// <<controller name, action name>, HTTP method>
|
// <<controller name, action name>, HTTP method>
|
||||||
|
{{u"app"_s, u"deleteAPIKey"_s}, Http::METHOD_POST},
|
||||||
{{u"app"_s, u"rotateAPIKey"_s}, Http::METHOD_POST},
|
{{u"app"_s, u"rotateAPIKey"_s}, Http::METHOD_POST},
|
||||||
{{u"app"_s, u"sendTestEmail"_s}, Http::METHOD_POST},
|
{{u"app"_s, u"sendTestEmail"_s}, Http::METHOD_POST},
|
||||||
{{u"app"_s, u"setCookies"_s}, Http::METHOD_POST},
|
{{u"app"_s, u"setCookies"_s}, Http::METHOD_POST},
|
||||||
|
|||||||
@ -1,24 +1,24 @@
|
|||||||
<div id="confirmRotateAPIKeyDialog">
|
<div id="confirmAPIKeyDialog">
|
||||||
<div class="genericConfirmGrid">
|
<div class="genericConfirmGrid">
|
||||||
<span class="confirmGridItem confirmWarning"></span>
|
<span class="confirmGridItem confirmWarning"></span>
|
||||||
<span class="confirmGridItem dialogMessage"></span>
|
<span class="confirmGridItem dialogMessage"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="button" value="QBT_TR(Yes)QBT_TR[CONTEXT=MainWindow]" id="confirmRotateButton">
|
<input type="button" value="QBT_TR(Yes)QBT_TR[CONTEXT=MainWindow]" id="confirmAPIKeyButton">
|
||||||
<input type="button" value="QBT_TR(No)QBT_TR[CONTEXT=MainWindow]" id="cancelRotateButton">
|
<input type="button" value="QBT_TR(No)QBT_TR[CONTEXT=MainWindow]" id="cancelAPIKeyButton">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const { windowEl, options } = window.MUI.Windows.instances["confirmRotateAPIKeyDialog"];
|
const { windowEl, options } = window.MUI.Windows.instances["confirmAPIKeyDialog"];
|
||||||
const { message } = options.data;
|
const { message, action } = options.data;
|
||||||
|
|
||||||
const confirmButton = document.getElementById("confirmRotateButton");
|
const confirmButton = document.getElementById("confirmAPIKeyButton");
|
||||||
const cancelButton = document.getElementById("cancelRotateButton");
|
const cancelButton = document.getElementById("cancelAPIKeyButton");
|
||||||
const dialog = document.getElementById("confirmRotateAPIKeyDialog");
|
const dialog = document.getElementById("confirmAPIKeyDialog");
|
||||||
|
|
||||||
dialog.querySelector("span.dialogMessage").textContent = message;
|
dialog.querySelector("span.dialogMessage").textContent = message;
|
||||||
|
|
||||||
@ -26,7 +26,14 @@
|
|||||||
window.qBittorrent.Client.closeWindow(dialog);
|
window.qBittorrent.Client.closeWindow(dialog);
|
||||||
});
|
});
|
||||||
confirmButton.addEventListener("click", (e) => {
|
confirmButton.addEventListener("click", (e) => {
|
||||||
window.qBittorrent.Preferences.rotateAPIKey();
|
switch (action) {
|
||||||
|
case "rotate":
|
||||||
|
window.qBittorrent.Preferences.rotateAPIKey();
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
window.qBittorrent.Preferences.deleteAPIKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
window.qBittorrent.Client.closeWindow(dialog);
|
window.qBittorrent.Client.closeWindow(dialog);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1012,6 +1012,11 @@
|
|||||||
<img src="images/force-recheck.svg" alt="QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]" title="QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]" width="16" height="16" style="margin: 4px; top: 2px; position: relative;">
|
<img src="images/force-recheck.svg" alt="QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]" title="QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]" width="16" height="16" style="margin: 4px; top: 2px; position: relative;">
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" disabled id="webUIAPIKeyDeleteButton" style="padding: 0;" data-has-key="false" aria-label="QBT_TR(Delete API key)QBT_TR[CONTEXT=OptionsDialog]">
|
||||||
|
<img src="images/list-remove.svg" alt="QBT_TR(Delete API key)QBT_TR[CONTEXT=OptionsDialog]" title="QBT_TR(Delete API key)QBT_TR[CONTEXT=OptionsDialog]" width="16" height="16" style="margin: 4px; top: 2px; position: relative;">
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -1823,6 +1828,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
|||||||
updateWebuiLocaleSelect: updateWebuiLocaleSelect,
|
updateWebuiLocaleSelect: updateWebuiLocaleSelect,
|
||||||
registerDynDns: registerDynDns,
|
registerDynDns: registerDynDns,
|
||||||
rotateAPIKey: rotateAPIKey,
|
rotateAPIKey: rotateAPIKey,
|
||||||
|
deleteAPIKey: deleteAPIKey,
|
||||||
applyPreferences: applyPreferences
|
applyPreferences: applyPreferences
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -2586,6 +2592,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
|||||||
document.getElementById("webUIAPIKeyCopyButton").disabled = false;
|
document.getElementById("webUIAPIKeyCopyButton").disabled = false;
|
||||||
document.getElementById("webUIAPIKeyRotateButton").dataset.hasKey = "true";
|
document.getElementById("webUIAPIKeyRotateButton").dataset.hasKey = "true";
|
||||||
document.querySelector("#webUIAPIKeyRotateButton img").title = "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
document.querySelector("#webUIAPIKeyRotateButton img").title = "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
|
document.getElementById("webUIAPIKeyDeleteButton").disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use alternative WebUI
|
// Use alternative WebUI
|
||||||
@ -3287,12 +3294,37 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
|||||||
document.getElementById("webUIAPIKeyCopyButton").disabled = false;
|
document.getElementById("webUIAPIKeyCopyButton").disabled = false;
|
||||||
document.getElementById("webUIAPIKeyRotateButton").dataset.hasKey = "true";
|
document.getElementById("webUIAPIKeyRotateButton").dataset.hasKey = "true";
|
||||||
document.querySelector("#webUIAPIKeyRotateButton img").title = "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
document.querySelector("#webUIAPIKeyRotateButton img").title = "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
|
document.getElementById("webUIAPIKeyDeleteButton").disabled = false;
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
alert(`QBT_TR(Unable to rotate API key.)QBT_TR[CONTEXT=HttpServer] ${error.toString()}`);
|
alert(`QBT_TR(Unable to rotate API key.)QBT_TR[CONTEXT=HttpServer] ${error.toString()}`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deleteAPIKey = () => {
|
||||||
|
fetch("api/v2/app/deleteAPIKey", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
.then(async (response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
alert(await response.text());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiKeyTextElem = document.getElementById("WebUIAPIKeyText");
|
||||||
|
apiKeyTextElem.value = "";
|
||||||
|
apiKeyTextElem.dataset.apiKey = "";
|
||||||
|
|
||||||
|
document.getElementById("webUIAPIKeyCopyButton").disabled = true;
|
||||||
|
document.getElementById("webUIAPIKeyRotateButton").dataset.hasKey = "false";
|
||||||
|
document.querySelector("#webUIAPIKeyRotateButton img").title = "QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
|
document.getElementById("webUIAPIKeyDeleteButton").disabled = true;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert(`QBT_TR(Unable to delete API key.)QBT_TR[CONTEXT=HttpServer] ${error.toString()}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById("webUIAPIKeyCopyButton").addEventListener("click", async (e) => {
|
document.getElementById("webUIAPIKeyCopyButton").addEventListener("click", async (e) => {
|
||||||
const apiKey = document.getElementById("WebUIAPIKeyText").dataset.apiKey;
|
const apiKey = document.getElementById("WebUIAPIKeyText").dataset.apiKey;
|
||||||
await clipboardCopy(apiKey);
|
await clipboardCopy(apiKey);
|
||||||
@ -3310,7 +3342,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("webUIAPIKeyRotateButton").addEventListener("click", (e) => {
|
document.getElementById("webUIAPIKeyRotateButton").addEventListener("click", (e) => {
|
||||||
const hasKey = e.target.parentElement.dataset.hasKey;
|
const hasKey = e.target.parentElement.dataset.hasKey === "true";
|
||||||
const title = hasKey
|
const title = hasKey
|
||||||
? "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]"
|
? "QBT_TR(Rotate API key)QBT_TR[CONTEXT=OptionsDialog]"
|
||||||
: "QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
: "QBT_TR(Generate API key)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
@ -3320,11 +3352,26 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
|||||||
|
|
||||||
new MochaUI.Modal({
|
new MochaUI.Modal({
|
||||||
...window.qBittorrent.Dialog.baseModalOptions,
|
...window.qBittorrent.Dialog.baseModalOptions,
|
||||||
id: "confirmRotateAPIKeyDialog",
|
|
||||||
title: title,
|
title: title,
|
||||||
contentURL: "views/confirmRotateAPIKey.html?v=${CACHEID}",
|
id: "confirmAPIKeyDialog",
|
||||||
|
contentURL: "views/confirmAPIKey.html?v=${CACHEID}",
|
||||||
data: {
|
data: {
|
||||||
hasKey: hasKey,
|
action: "rotate",
|
||||||
|
message: message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("webUIAPIKeyDeleteButton").addEventListener("click", (e) => {
|
||||||
|
const title = "QBT_TR(Delete API key)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
|
const message = "QBT_TR(Delete this API key? The current key will immediately stop working.)QBT_TR[CONTEXT=confirmRotateAPIKeyDialog]";
|
||||||
|
new MochaUI.Modal({
|
||||||
|
...window.qBittorrent.Dialog.baseModalOptions,
|
||||||
|
title: title,
|
||||||
|
id: "confirmAPIKeyDialog",
|
||||||
|
contentURL: "views/confirmAPIKey.html?v=${CACHEID}",
|
||||||
|
data: {
|
||||||
|
action: "delete",
|
||||||
message: message,
|
message: message,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -424,7 +424,7 @@
|
|||||||
<file>private/views/confirmAutoTMM.html</file>
|
<file>private/views/confirmAutoTMM.html</file>
|
||||||
<file>private/views/confirmdeletion.html</file>
|
<file>private/views/confirmdeletion.html</file>
|
||||||
<file>private/views/confirmRecheck.html</file>
|
<file>private/views/confirmRecheck.html</file>
|
||||||
<file>private/views/confirmRotateAPIKey.html</file>
|
<file>private/views/confirmAPIKey.html</file>
|
||||||
<file>private/views/cookies.html</file>
|
<file>private/views/cookies.html</file>
|
||||||
<file>private/views/createtorrent.html</file>
|
<file>private/views/createtorrent.html</file>
|
||||||
<file>private/views/filters.html</file>
|
<file>private/views/filters.html</file>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user