Define basic library structure
This commit is contained in:
@@ -8,18 +8,26 @@ You will probably need to install ***uvicorn*** to launch a server built with Fa
|
|||||||
python3 -m pip install "uvicorn[standard]"
|
python3 -m pip install "uvicorn[standard]"
|
||||||
```
|
```
|
||||||
|
|
||||||
After importing an app such as
|
After importing an app such as `main.py`:
|
||||||
|
|
||||||
main.py:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from vue_apps_py.vue_app_server import VueApp
|
from src.vue_apps_py.security import SecurityHelper
|
||||||
|
from src.vue_apps_py.server import VueApp
|
||||||
|
from src.vue_apps_py.client import ClientAPI
|
||||||
|
from src.vue_apps_py.server_utils.models import Intent
|
||||||
|
|
||||||
app = VueApp()
|
# Initialize API
|
||||||
|
api = ClientAPI(client_id='vue-app-0', client_secret='abccf12389efab222')
|
||||||
|
|
||||||
|
# Prepare Security
|
||||||
|
key_holder = SecurityHelper(public_key='abbcbbbcaksjdhf/skdjhfnnsn/sjdkfjj21234=')
|
||||||
|
|
||||||
|
# Get Vue Application Server
|
||||||
|
vue_app = VueApp(client_api=api, security_helper=key_holder, intents=[Intent.INLINE_QUERY], debug=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
You can launch web server:
|
You can launch web server:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
uvicorn main:app --reload
|
uvicorn test:vue_app --reload
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ build-backend = "setuptools.build_meta"
|
|||||||
[project]
|
[project]
|
||||||
name = "vue_apps_py"
|
name = "vue_apps_py"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = [{ name = "ArbinaHQ", email = "hey@arbina.com" }]
|
authors = [{ name = "Arbina", email = "havlong@arbina.com" }]
|
||||||
description = "Python library for building Vue Apps"
|
description = "Python library for building Vue Apps"
|
||||||
readme = "README.MD"
|
readme = "README.MD"
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.7"
|
||||||
classifiers = ["Programming Language :: Python :: 3", "Operating System :: OS Independent"]
|
classifiers = ["Programming Language :: Python :: 3", "Operating System :: OS Independent"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|||||||
10
vue-apps-py/src/vue_apps_py/client.py
Normal file
10
vue-apps-py/src/vue_apps_py/client.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
class ClientAPI:
|
||||||
|
client_id: str
|
||||||
|
client_secret: str
|
||||||
|
|
||||||
|
def __init__(self, client_id: str, client_secret: str):
|
||||||
|
self.client_id = client_id
|
||||||
|
self.client_secret = client_secret
|
||||||
|
|
||||||
|
def get_token(self) -> str:
|
||||||
|
return self.client_secret
|
||||||
15
vue-apps-py/src/vue_apps_py/security.py
Normal file
15
vue-apps-py/src/vue_apps_py/security.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from ed25519.keys import VerifyingKey
|
||||||
|
|
||||||
|
|
||||||
|
class SecurityHelper:
|
||||||
|
public_key: VerifyingKey
|
||||||
|
|
||||||
|
def __init__(self, public_key: str):
|
||||||
|
self.public_key = VerifyingKey(public_key.encode(), encoding='base64')
|
||||||
|
|
||||||
|
def check(self, http: bytes, signature: bytes) -> bool:
|
||||||
|
try:
|
||||||
|
self.public_key.verify(signature, http, encoding='base64')
|
||||||
|
return True
|
||||||
|
except AssertionError:
|
||||||
|
return False
|
||||||
38
vue-apps-py/src/vue_apps_py/server.py
Normal file
38
vue-apps-py/src/vue_apps_py/server.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from fastapi import FastAPI, Request, HTTPException
|
||||||
|
|
||||||
|
from client import ClientAPI
|
||||||
|
from security import SecurityHelper
|
||||||
|
from server_utils.models import PongModel, Intent
|
||||||
|
|
||||||
|
|
||||||
|
def VueApp(client_api: ClientAPI, security_helper: SecurityHelper, intents: List[Intent], debug: bool = False):
|
||||||
|
app = FastAPI(debug=debug, title='VueApp', description='Vue Application Server', version='0.0.1')
|
||||||
|
|
||||||
|
async def check_request(request: Request) -> bool:
|
||||||
|
if 'X-Signature-Ed25519' not in request.headers or 'X-Signature-Timestamp' not in request.headers:
|
||||||
|
return False
|
||||||
|
body_to_verify = await request.body()
|
||||||
|
timestamp = request.headers['X-Signature-Timestamp'].encode('utf-8')
|
||||||
|
signature = request.headers['X-Signature-Ed25519'].encode('utf-8')
|
||||||
|
return security_helper.check(timestamp + body_to_verify, signature)
|
||||||
|
|
||||||
|
@app.post(path='/ping', response_model=PongModel)
|
||||||
|
async def handle_ping(request: Request) -> PongModel:
|
||||||
|
ok = await check_request(request)
|
||||||
|
if not ok:
|
||||||
|
raise HTTPException(status_code=401, detail='Verification of signature failed')
|
||||||
|
|
||||||
|
return PongModel(message='pong', token=client_api.get_token())
|
||||||
|
|
||||||
|
if Intent.INLINE_QUERY in intents:
|
||||||
|
@app.post(path='/auto', response_model=PongModel)
|
||||||
|
async def handle_autocomplete(request: Request) -> PongModel:
|
||||||
|
ok = await check_request(request)
|
||||||
|
if not ok:
|
||||||
|
raise HTTPException(status_code=401, detail='Verification of signature failed')
|
||||||
|
|
||||||
|
return PongModel(message='pong', token=client_api.get_token())
|
||||||
|
|
||||||
|
return app
|
||||||
20
vue-apps-py/src/vue_apps_py/server_utils/models.py
Normal file
20
vue-apps-py/src/vue_apps_py/server_utils/models.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from enum import Enum, auto
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
|
class PingModel(BaseModel):
|
||||||
|
nickname: str
|
||||||
|
|
||||||
|
|
||||||
|
class PongModel(BaseModel):
|
||||||
|
message: str = Field(default='ping', title='Message', description='Message answered on pings')
|
||||||
|
token: Optional[str] = Field(default=None, title='Token', description='Token for API to check')
|
||||||
|
|
||||||
|
|
||||||
|
class Intent(Enum):
|
||||||
|
PAGE_APP = auto()
|
||||||
|
PAGE_MENTIONS = auto()
|
||||||
|
INLINE_QUERY = auto()
|
||||||
|
INTERACTIONS = auto()
|
||||||
Reference in New Issue
Block a user