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,8 +1,12 @@
|
|||||||
# Miscellaneous Actions
|
# 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
|
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
|
properly with each other. New versions of AnkiConnect are backwards compatible; as long as you are using actions
|
||||||
@ -11,18 +15,50 @@
|
|||||||
*Sample request*:
|
*Sample request*:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"action": "version",
|
"action": "requestPermission",
|
||||||
"version": 6
|
"version": 6
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*Sample result*:
|
*Samples results*:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"result": 6,
|
"result": {
|
||||||
|
"permission": "granted",
|
||||||
|
"requireApiKey": false,
|
||||||
|
"version": 6
|
||||||
|
},
|
||||||
"error": null
|
"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
|
||||||
|
{
|
||||||
|
"action": "version",
|
||||||
|
"version": 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Sample result*:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result": 6,
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* **sync**
|
* **sync**
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import string
|
|||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
|
from PyQt5 import QtCore
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ class AnkiConnect:
|
|||||||
reply = {'result': None, 'error': None}
|
reply = {'result': None, 'error': None}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if key != util.setting('apiKey'):
|
if key != util.setting('apiKey') and name != 'requestPermission':
|
||||||
raise Exception('valid api key must be provided')
|
raise Exception('valid api key must be provided')
|
||||||
|
|
||||||
method = None
|
method = None
|
||||||
@ -311,6 +312,55 @@ class AnkiConnect:
|
|||||||
def version(self):
|
def version(self):
|
||||||
return util.setting('apiVersion')
|
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()
|
@util.api()
|
||||||
def getProfiles(self):
|
def getProfiles(self):
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
"apiLogPath": null,
|
"apiLogPath": null,
|
||||||
"webBindAddress": "127.0.0.1",
|
"webBindAddress": "127.0.0.1",
|
||||||
"webBindPort": 8765,
|
"webBindPort": 8765,
|
||||||
"webCorsOriginList": ["http://localhost"]
|
"webCorsOriginList": ["http://localhost"],
|
||||||
|
"ignoreOriginList": []
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ def setting(key):
|
|||||||
'webBindPort': 8765,
|
'webBindPort': 8765,
|
||||||
'webCorsOrigin': os.getenv('ANKICONNECT_CORS_ORIGIN', None),
|
'webCorsOrigin': os.getenv('ANKICONNECT_CORS_ORIGIN', None),
|
||||||
'webCorsOriginList': ['http://localhost'],
|
'webCorsOriginList': ['http://localhost'],
|
||||||
|
'ignoreOriginList': [],
|
||||||
'webTimeout': 10000,
|
'webTimeout': 10000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,16 +185,25 @@ class WebServer:
|
|||||||
allowed = True
|
allowed = True
|
||||||
|
|
||||||
resp = bytes()
|
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:
|
if len(req.body) == 0:
|
||||||
body = 'AnkiConnect v.{}'.format(util.setting('apiVersion')).encode('utf-8')
|
body = 'AnkiConnect v.{}'.format(util.setting('apiVersion')).encode('utf-8')
|
||||||
else:
|
else:
|
||||||
try:
|
if params.get('action', '') == 'requestPermission':
|
||||||
params = json.loads(req.body.decode('utf-8'))
|
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')
|
body = json.dumps(self.handler(params)).encode('utf-8')
|
||||||
except ValueError:
|
|
||||||
body = json.dumps(None).encode('utf-8')
|
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
['HTTP/1.1 200 OK', None],
|
['HTTP/1.1 200 OK', None],
|
||||||
|
Loading…
Reference in New Issue
Block a user