Add requestPermission API method (#255)
* Add requestPermission Api Method * Add documentation about requestPermission method * Update version documentation
This commit is contained in:
parent
17d8ecf60f
commit
9fec86f7fe
@ -1,13 +1,49 @@
|
||||
# Miscellaneous Actions
|
||||
|
||||
* **version**
|
||||
* **requestPermission**
|
||||
|
||||
Gets the version of the API exposed by this plugin. Currently versions `1` through `6` are defined.
|
||||
Request permission to use the API exposed by this plugin. Only request coming from origin listed in the
|
||||
`webCorsOriginList` option are allowed to use the Api. Calling this method will display a popup asking the user
|
||||
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
|
||||
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.
|
||||
|
||||
This should be the first call you make to make sure that your application and AnkiConnect are able to communicate
|
||||
properly with each other. New versions of AnkiConnect are backwards compatible; as long as you are using actions
|
||||
which are available in the reported AnkiConnect version or earlier, everything should work fine.
|
||||
|
||||
*Sample request*:
|
||||
```json
|
||||
{
|
||||
"action": "requestPermission",
|
||||
"version": 6
|
||||
}
|
||||
```
|
||||
|
||||
*Samples results*:
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"permission": "granted",
|
||||
"requireApiKey": false,
|
||||
"version": 6
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"permission": "denied"
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
* **version**
|
||||
|
||||
Gets the version of the API exposed by this plugin. Currently versions `1` through `6` are defined.
|
||||
|
||||
*Sample request*:
|
||||
```json
|
||||
{
|
||||
|
@ -26,6 +26,7 @@ import string
|
||||
import time
|
||||
import unicodedata
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
@ -97,7 +98,7 @@ class AnkiConnect:
|
||||
reply = {'result': None, 'error': None}
|
||||
|
||||
try:
|
||||
if key != util.setting('apiKey'):
|
||||
if key != util.setting('apiKey') and name != 'requestPermission':
|
||||
raise Exception('valid api key must be provided')
|
||||
|
||||
method = None
|
||||
@ -311,6 +312,55 @@ class AnkiConnect:
|
||||
def version(self):
|
||||
return util.setting('apiVersion')
|
||||
|
||||
@util.api()
|
||||
def requestPermission(self, origin, 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 = {
|
||||
"permission": "granted",
|
||||
"requireApikey": bool(util.setting('apiKey')),
|
||||
"version": util.setting('apiVersion')
|
||||
}
|
||||
else :
|
||||
results = {
|
||||
"permission": "denied",
|
||||
}
|
||||
return results
|
||||
|
||||
|
||||
@util.api()
|
||||
def getProfiles(self):
|
||||
|
@ -3,5 +3,6 @@
|
||||
"apiLogPath": null,
|
||||
"webBindAddress": "127.0.0.1",
|
||||
"webBindPort": 8765,
|
||||
"webCorsOriginList": ["http://localhost"]
|
||||
"webCorsOriginList": ["http://localhost"],
|
||||
"ignoreOriginList": []
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ def setting(key):
|
||||
'webBindPort': 8765,
|
||||
'webCorsOrigin': os.getenv('ANKICONNECT_CORS_ORIGIN', None),
|
||||
'webCorsOriginList': ['http://localhost'],
|
||||
'ignoreOriginList': [],
|
||||
'webTimeout': 10000,
|
||||
}
|
||||
|
||||
|
@ -185,16 +185,25 @@ class WebServer:
|
||||
allowed = True
|
||||
|
||||
resp = bytes()
|
||||
paramsError = False
|
||||
try:
|
||||
params = json.loads(req.body.decode('utf-8'))
|
||||
except ValueError:
|
||||
body = json.dumps(None).encode('utf-8')
|
||||
paramsError = True
|
||||
|
||||
if allowed :
|
||||
if allowed or not paramsError and params.get('action', '') == 'requestPermission':
|
||||
if len(req.body) == 0:
|
||||
body = 'AnkiConnect v.{}'.format(util.setting('apiVersion')).encode('utf-8')
|
||||
else:
|
||||
try:
|
||||
params = json.loads(req.body.decode('utf-8'))
|
||||
if params.get('action', '') == 'requestPermission':
|
||||
params['params'] = params.get('params', {})
|
||||
params['params']['allowed'] = allowed
|
||||
params['params']['origin'] = b'origin' in req.headers and req.headers[b'origin'].decode() or ''
|
||||
if not allowed :
|
||||
corsOrigin = params['params']['origin']
|
||||
|
||||
body = json.dumps(self.handler(params)).encode('utf-8')
|
||||
except ValueError:
|
||||
body = json.dumps(None).encode('utf-8')
|
||||
|
||||
headers = [
|
||||
['HTTP/1.1 200 OK', None],
|
||||
|
Loading…
Reference in New Issue
Block a user