requestPermission: improve UX & docs (#312)
* requestPermission: change Ignore button to checkbox * Update requestPermission documentation - describe the possible results - document ignoreOriginList
This commit is contained in:
parent
8e9879f80f
commit
81fccbfac6
17
README.md
17
README.md
@ -1455,11 +1455,18 @@ corresponding to when the API was available for use.
|
|||||||
|
|
||||||
* **requestPermission**
|
* **requestPermission**
|
||||||
|
|
||||||
Request permission to use the API exposed by this plugin. Only request coming from origin listed in the
|
Requests permission to use the API exposed by this plugin. This method does not require the API key, and is the
|
||||||
`webCorsOriginList` option are allowed to use the Api. Calling this method will display a popup asking the user
|
only one that accepts requests from any origin; the other methods only accept requests from trusted origins,
|
||||||
if he want to allow your origin to use the Api. This is the only method that can be called even if the origin of
|
which are listed under `webCorsOriginList` in the add-on config. `localhost` is trusted by default.
|
||||||
the request isn't in the `webCorsOriginList` list. It also doesn't require the api key. Calling this method will
|
|
||||||
not display the popup if the origin is already trusted.
|
Calling this method from an untrusted origin will display a popup in Anki asking the user whether they want to
|
||||||
|
allow your origin to use the API; calls from trusted origins will return the result without displaying the popup.
|
||||||
|
When denying permission, the user may also choose to ignore further permission requests from that origin. These
|
||||||
|
origins end up in the `ignoreOriginList`, editable via the add-on config.
|
||||||
|
|
||||||
|
The result always contains the `permission` field, which in turn contains either the string `granted` or `denied`,
|
||||||
|
corresponding to whether your origin is trusted. If your origin is trusted, the fields `requireApiKey` (`true` if
|
||||||
|
required) and `version` will also be returned.
|
||||||
|
|
||||||
This should be the first call you make to make sure that your application and Anki-Connect are able to communicate
|
This should be the first call you make to make sure that your application and Anki-Connect are able to communicate
|
||||||
properly with each other. New versions of Anki-Connect are backwards compatible; as long as you are using actions
|
properly with each other. New versions of Anki-Connect are backwards compatible; as long as you are using actions
|
||||||
|
@ -28,7 +28,7 @@ import unicodedata
|
|||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
from PyQt5.QtWidgets import QMessageBox, QCheckBox
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
import anki.exporting
|
import anki.exporting
|
||||||
@ -364,53 +364,56 @@ class AnkiConnect:
|
|||||||
def version(self):
|
def version(self):
|
||||||
return util.setting('apiVersion')
|
return util.setting('apiVersion')
|
||||||
|
|
||||||
|
|
||||||
@util.api()
|
@util.api()
|
||||||
def requestPermission(self, origin, allowed):
|
def requestPermission(self, origin, allowed):
|
||||||
|
results = {
|
||||||
|
"permission": "denied",
|
||||||
|
}
|
||||||
|
|
||||||
if allowed:
|
if allowed:
|
||||||
return {
|
|
||||||
"permission": "granted",
|
|
||||||
"requireApikey": bool(util.setting('apiKey')),
|
|
||||||
"version": util.setting('apiVersion')
|
|
||||||
}
|
|
||||||
|
|
||||||
if origin in util.setting('ignoreOriginList') :
|
|
||||||
return {
|
|
||||||
"permission": "denied",
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = QMessageBox(None)
|
|
||||||
msg.setWindowTitle("A website want to access to Anki")
|
|
||||||
msg.setText(origin + " request permission to use Anki through AnkiConnect.\nDo you want to give it access ?")
|
|
||||||
msg.setInformativeText("By giving permission, the website will be able to do actions on anki, including destructives actions like deck deletion.")
|
|
||||||
msg.setWindowIcon(self.window().windowIcon())
|
|
||||||
msg.setIcon(QMessageBox.Question)
|
|
||||||
msg.setStandardButtons(QMessageBox.Yes|QMessageBox.Ignore|QMessageBox.No)
|
|
||||||
msg.setDefaultButton(QMessageBox.No)
|
|
||||||
msg.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
|
|
||||||
pressedButton = msg.exec_()
|
|
||||||
|
|
||||||
if pressedButton == QMessageBox.Yes:
|
|
||||||
config = aqt.mw.addonManager.getConfig(__name__)
|
|
||||||
config["webCorsOriginList"] = util.setting('webCorsOriginList')
|
|
||||||
config["webCorsOriginList"].append(origin)
|
|
||||||
aqt.mw.addonManager.writeConfig(__name__, config)
|
|
||||||
|
|
||||||
if pressedButton == QMessageBox.Ignore:
|
|
||||||
config = aqt.mw.addonManager.getConfig(__name__)
|
|
||||||
config["ignoreOriginList"] = util.setting('ignoreOriginList')
|
|
||||||
config["ignoreOriginList"].append(origin)
|
|
||||||
aqt.mw.addonManager.writeConfig(__name__, config)
|
|
||||||
|
|
||||||
if pressedButton == QMessageBox.Yes:
|
|
||||||
results = {
|
results = {
|
||||||
"permission": "granted",
|
"permission": "granted",
|
||||||
"requireApikey": bool(util.setting('apiKey')),
|
"requireApikey": bool(util.setting('apiKey')),
|
||||||
"version": util.setting('apiVersion')
|
"version": util.setting('apiVersion')
|
||||||
}
|
|
||||||
else :
|
|
||||||
results = {
|
|
||||||
"permission": "denied",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elif origin in util.setting('ignoreOriginList'):
|
||||||
|
pass # defaults to denied
|
||||||
|
|
||||||
|
else: # prompt the user
|
||||||
|
msg = QMessageBox(None)
|
||||||
|
msg.setWindowTitle("A website wants to access to Anki")
|
||||||
|
msg.setText('"{}" requests permission to use Anki through AnkiConnect. Do you want to give it access?'.format(origin))
|
||||||
|
msg.setInformativeText("By granting permission, you'll allow the website to modify your collection on your behalf, including the execution of destructive actions such as deck deletion.")
|
||||||
|
msg.setWindowIcon(self.window().windowIcon())
|
||||||
|
msg.setIcon(QMessageBox.Question)
|
||||||
|
msg.setStandardButtons(QMessageBox.Yes|QMessageBox.No)
|
||||||
|
msg.setDefaultButton(QMessageBox.No)
|
||||||
|
msg.setCheckBox(QCheckBox(text='Ignore further requests from "{}"'.format(origin), parent=msg))
|
||||||
|
msg.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
|
||||||
|
pressedButton = msg.exec_()
|
||||||
|
|
||||||
|
if pressedButton == QMessageBox.Yes:
|
||||||
|
config = aqt.mw.addonManager.getConfig(__name__)
|
||||||
|
config["webCorsOriginList"] = util.setting('webCorsOriginList')
|
||||||
|
config["webCorsOriginList"].append(origin)
|
||||||
|
aqt.mw.addonManager.writeConfig(__name__, config)
|
||||||
|
results = {
|
||||||
|
"permission": "granted",
|
||||||
|
"requireApikey": bool(util.setting('apiKey')),
|
||||||
|
"version": util.setting('apiVersion')
|
||||||
|
}
|
||||||
|
|
||||||
|
# if the origin isn't an empty string, the user clicks "No", and the ignore box is checked
|
||||||
|
elif origin and pressedButton == QMessageBox.No and msg.checkBox().isChecked():
|
||||||
|
config = aqt.mw.addonManager.getConfig(__name__)
|
||||||
|
config["ignoreOriginList"] = util.setting('ignoreOriginList')
|
||||||
|
config["ignoreOriginList"].append(origin)
|
||||||
|
aqt.mw.addonManager.writeConfig(__name__, config)
|
||||||
|
|
||||||
|
# else defaults to denied
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user