Merge pull request #446 from arcbtc/FastAPI

Fixes lnaddress
This commit is contained in:
Arc 2021-11-30 16:15:00 +00:00 committed by GitHub
commit 152d0c3c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 97 deletions

View File

@ -1,51 +0,0 @@
from fastapi import Request, HTTPException
from fastapi.security.api_key import APIKeyQuery, APIKeyCookie, APIKeyHeader, APIKey
# https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680
from fastapi import Security, Depends, FastAPI, HTTPException
from fastapi.security.api_key import APIKeyQuery, APIKeyCookie, APIKeyHeader, APIKey
from fastapi.security.base import SecurityBase
API_KEY = "usr"
API_KEY_NAME = "X-API-key"
api_key_query = APIKeyQuery(name=API_KEY_NAME, auto_error=False)
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
class AuthBearer(SecurityBase):
def __init__(self, scheme_name: str = None, auto_error: bool = True):
self.scheme_name = scheme_name or self.__class__.__name__
self.auto_error = auto_error
async def __call__(self, request: Request):
key = await self.get_api_key()
print(key)
# credentials: HTTPAuthorizationCredentials = await super(AuthBearer, self).__call__(request)
# if credentials:
# if not credentials.scheme == "Bearer":
# raise HTTPException(
# status_code=403, detail="Invalid authentication scheme.")
# if not self.verify_jwt(credentials.credentials):
# raise HTTPException(
# status_code=403, detail="Invalid token or expired token.")
# return credentials.credentials
# else:
# raise HTTPException(
# status_code=403, detail="Invalid authorization code.")
async def get_api_key(
self,
api_key_query: str = Security(api_key_query),
api_key_header: str = Security(api_key_header),
):
if api_key_query == API_KEY:
return api_key_query
elif api_key_header == API_KEY:
return api_key_header
else:
raise HTTPException(
status_code=403, detail="Could not validate credentials"
)

View File

@ -4,18 +4,16 @@ from typing import Optional
from fastapi import Request, status
from fastapi.exceptions import HTTPException
from fastapi.param_functions import Body
from fastapi.params import Depends, Query
from fastapi.responses import FileResponse, RedirectResponse
from fastapi.routing import APIRouter
from pydantic.types import UUID4
from starlette.responses import HTMLResponse
from starlette.responses import HTMLResponse, JSONResponse
from lnbits.core import db
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from lnbits.helpers import template_renderer, url_for
from lnbits.requestvars import g
from lnbits.settings import LNBITS_ALLOWED_USERS, LNBITS_SITE_TITLE, SERVICE_FEE
from ..crud import (
@ -32,7 +30,7 @@ from ..services import pay_invoice, redeem_lnurl_withdraw
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
@core_html_routes.get("/favicon.ico")
@core_html_routes.get("/favicon.ico", response_class=FileResponse)
async def favicon():
return FileResponse("lnbits/core/static/favicon.ico")
@ -44,7 +42,11 @@ async def home(request: Request, lightning: str = None):
)
@core_html_routes.get("/extensions", name="core.extensions")
@core_html_routes.get(
"/extensions",
name="core.extensions",
response_class=HTMLResponse,
)
async def extensions(
request: Request,
user: User = Depends(check_user_exists),
@ -77,9 +79,19 @@ async def extensions(
)
@core_html_routes.get("/wallet", response_class=HTMLResponse)
# Not sure how to validate
# @validate_uuids(["usr", "nme"])
@core_html_routes.get(
"/wallet",
response_class=HTMLResponse,
description="""
Args:
just **wallet_name**: create a new user, then create a new wallet for user with wallet_name<br>
just **user_id**: return the first user wallet or create one if none found (with default wallet_name)<br>
**user_id** and **wallet_name**: create a new wallet for user with wallet_name<br>
**user_id** and **wallet_id**: return that wallet if user is the owner<br>
nothing: create everything<br>
""",
)
async def wallet(
request: Request = Query(None),
nme: Optional[str] = Query(None),
@ -91,12 +103,6 @@ async def wallet(
wallet_name = nme
service_fee = int(SERVICE_FEE) if int(SERVICE_FEE) == SERVICE_FEE else SERVICE_FEE
# just wallet_name: create a new user, then create a new wallet for user with wallet_name
# just user_id: return the first user wallet or create one if none found (with default wallet_name)
# user_id and wallet_name: create a new wallet for user with wallet_name
# user_id and wallet_id: return that wallet if user is the owner
# nothing: create everything
if not user_id:
user = await get_user((await create_account()).id)
else:
@ -137,14 +143,13 @@ async def wallet(
)
@core_html_routes.get("/withdraw")
# @validate_uuids(["usr", "wal"], required=True)
@core_html_routes.get("/withdraw", response_class=JSONResponse)
async def lnurl_full_withdraw(request: Request):
user = await get_user(request.args.get("usr"))
user = await get_user(request.query_params.get("usr"))
if not user:
return {"status": "ERROR", "reason": "User does not exist."}
wallet = user.get_wallet(request.args.get("wal"))
wallet = user.get_wallet(request.query_params.get("wal"))
if not wallet:
return {"status": "ERROR", "reason": "Wallet does not exist."}
@ -159,18 +164,17 @@ async def lnurl_full_withdraw(request: Request):
}
@core_html_routes.get("/withdraw/cb")
# @validate_uuids(["usr", "wal"], required=True)
@core_html_routes.get("/withdraw/cb", response_class=JSONResponse)
async def lnurl_full_withdraw_callback(request: Request):
user = await get_user(request.args.get("usr"))
user = await get_user(request.query_params.get("usr"))
if not user:
return {"status": "ERROR", "reason": "User does not exist."}
wallet = user.get_wallet(request.args.get("wal"))
wallet = user.get_wallet(request.query_params.get("wal"))
if not wallet:
return {"status": "ERROR", "reason": "Wallet does not exist."}
pr = request.args.get("pr")
pr = request.query_params.get("pr")
async def pay():
try:
@ -180,14 +184,14 @@ async def lnurl_full_withdraw_callback(request: Request):
asyncio.create_task(pay())
balance_notify = request.args.get("balanceNotify")
balance_notify = request.query_params.get("balanceNotify")
if balance_notify:
await save_balance_notify(wallet.id, balance_notify)
return {"status": "OK"}
@core_html_routes.get("/deletewallet")
@core_html_routes.get("/deletewallet", response_class=RedirectResponse)
async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query(...)):
user = await get_user(usr)
user_wallet_ids = [u.id for u in user.wallets]
@ -211,14 +215,13 @@ async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query
@core_html_routes.get("/withdraw/notify/{service}")
# @validate_uuids(["wal"], required=True)
async def lnurl_balance_notify(request: Request, service: str):
bc = await get_balance_check(request.args.get("wal"), service)
bc = await get_balance_check(request.query_params.get("wal"), service)
if bc:
redeem_lnurl_withdraw(bc.wallet, bc.url)
@core_html_routes.get("/lnurlwallet")
@core_html_routes.get("/lnurlwallet", response_class=RedirectResponse)
async def lnurlwallet(request: Request):
async with db.connect() as conn:
account = await create_account(conn=conn)
@ -228,7 +231,7 @@ async def lnurlwallet(request: Request):
asyncio.create_task(
redeem_lnurl_withdraw(
wallet.id,
request.args.get("lightning"),
request.query_params.get("lightning"),
"LNbits initial funding: voucher redeem.",
{"tag": "lnurlwallet"},
5, # wait 5 seconds before sending the invoice to the service

View File

@ -176,7 +176,7 @@ async def purge_addresses(domain_id: str):
now = datetime.now().timestamp()
for row in rows:
r = Addresses(**row)._asdict()
r = Addresses(**row).dict()
start = datetime.fromtimestamp(r["time"])
paid = r["paid"]

View File

@ -370,10 +370,9 @@
if (data.wallet_endpoint == '') {
data.wallet_endpoint = null
}
data.wallet_endpoint = data.wallet_endpoint ?? '{{ request.url_root }}'
data.wallet_endpoint = data.wallet_endpoint ?? '{{ root_url }}'
data.duration = parseInt(data.duration)
console.log('data', data)
axios
.post('/lnaddress/api/v1/address/{{ domain_id }}', data)
.then(response => {

View File

@ -186,10 +186,14 @@
<q-input
filled
dense
bottom-slots
v-model.trim="domainDialog.data.cf_token"
type="text"
label="Cloudflare API token"
>
<template v-slot:hint>
Check extension <a href="https://github.com/lnbits/lnbits-legend/tree/master/lnbits/extensions/lnaddress">documentation!</a>
</template>
<q-tooltip class="bg-grey-8" anchor="bottom left" self="top left"
>Your API key in cloudflare</q-tooltip
>
@ -489,18 +493,6 @@
this.getDomains()
this.getAddresses()
}
// var self = this
//
// // axios is available for making requests
// axios({
// method: 'GET',
// url: '/example/api/v1/tools',
// headers: {
// 'X-example-header': 'not-used'
// }
// }).then(function (response) {
// self.tools = response.data
// })
}
})
</script>

View File

@ -1,4 +1,5 @@
from http import HTTPStatus
from urllib.parse import urlparse
from fastapi import Request
from fastapi.params import Depends
@ -34,7 +35,8 @@ async def display(domain_id, request: Request):
await purge_addresses(domain_id)
wallet = await get_wallet(domain.wallet)
url = urlparse(str(request.url))
return lnaddress_renderer().TemplateResponse(
"lnaddress/display.html",
{
@ -43,5 +45,6 @@ async def display(domain_id, request: Request):
"domain_domain": domain.domain,
"domain_cost": domain.cost,
"domain_wallet_inkey": wallet.inkey,
"root_url": f"{url.scheme}://{url.netloc}"
},
)