feat: code quality (#59)

* feat: code quality
* fixup!
This commit is contained in:
dni ⚡ 2024-08-05 11:49:50 +02:00 committed by GitHub
commit badc420069
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 3048 additions and 212 deletions

View file

@ -1,21 +1,25 @@
import json
import re
from http import HTTPStatus
from typing import Optional
from fastapi import Depends, Query, Request
from fastapi import APIRouter, Depends, Query, Request
from lnbits.core.crud import get_user, get_wallet
from lnbits.core.models import WalletTypeInfo
from lnbits.decorators import (
check_admin,
get_key_type,
require_admin_key,
require_invoice_key,
)
from lnbits.utils.exchange_rates import currencies, get_fiat_rate_satoshis
from lnurl.exceptions import InvalidUrl as LnurlInvalidUrl
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_user, get_wallet
from lnbits.decorators import WalletTypeInfo, check_admin, get_key_type, require_admin_key, require_invoice_key
from lnbits.utils.exchange_rates import currencies, get_fiat_rate_satoshis
from . import lnurlp_ext
from .crud import (
create_pay_link,
delete_lnurlp_settings,
delete_pay_link,
get_address_data,
get_or_create_lnurlp_settings,
get_pay_link,
get_pay_link_by_username,
@ -23,26 +27,18 @@ from .crud import (
update_lnurlp_settings,
update_pay_link,
)
from .services import check_lnaddress_format
from .helpers import parse_nostr_private_key
from .lnurl import api_lnurl_response
from .models import CreatePayLinkData, LnurlpSettings
# redirected from /.well-known/lnurlp
@lnurlp_ext.get("/api/v1/well-known/{username}")
async def lnaddress(username: str, request: Request):
address_data = await get_address_data(username)
assert address_data, "User not found"
return await api_lnurl_response(request, address_data.id, webhook_data=None)
lnurlp_api_router = APIRouter()
@lnurlp_ext.get("/api/v1/currencies")
@lnurlp_api_router.get("/api/v1/currencies")
async def api_list_currencies_available():
return list(currencies.keys())
@lnurlp_ext.get("/api/v1/links", status_code=HTTPStatus.OK)
@lnurlp_api_router.get("/api/v1/links", status_code=HTTPStatus.OK)
async def api_links(
req: Request,
wallet: WalletTypeInfo = Depends(get_key_type),
@ -60,14 +56,17 @@ async def api_links(
for link in await get_pay_links(wallet_ids)
]
except LnurlInvalidUrl:
except LnurlInvalidUrl as exc:
raise HTTPException(
status_code=HTTPStatus.UPGRADE_REQUIRED,
detail="LNURLs need to be delivered over a publically accessible `https` domain or Tor.",
)
detail=(
"LNURLs need to be delivered over a publicly "
"accessible `https` domain or Tor onion."
),
) from exc
@lnurlp_ext.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
@lnurlp_api_router.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_retrieve(
r: Request, link_id: str, key_info: WalletTypeInfo = Depends(require_invoice_key)
):
@ -80,7 +79,7 @@ async def api_link_retrieve(
link_wallet = await get_wallet(link.wallet)
if link_wallet.user != key_info.wallet.user:
if link_wallet and link_wallet.user != key_info.wallet.user:
raise HTTPException(
detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN
)
@ -96,8 +95,9 @@ async def check_username_exists(username: str):
status_code=HTTPStatus.BAD_REQUEST,
)
@lnurlp_ext.post("/api/v1/links", status_code=HTTPStatus.CREATED)
@lnurlp_ext.put("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
@lnurlp_api_router.post("/api/v1/links", status_code=HTTPStatus.CREATED)
@lnurlp_api_router.put("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_create_or_update(
data: CreatePayLinkData,
request: Request,
@ -119,20 +119,20 @@ async def api_link_create_or_update(
if data.webhook_headers:
try:
json.loads(data.webhook_headers)
except ValueError:
except ValueError as exc:
raise HTTPException(
detail="Invalid JSON in webhook_headers.",
status_code=HTTPStatus.BAD_REQUEST,
)
) from exc
if data.webhook_body:
try:
json.loads(data.webhook_body)
except ValueError:
except ValueError as exc:
raise HTTPException(
detail="Invalid JSON in webhook_body.",
status_code=HTTPStatus.BAD_REQUEST,
)
) from exc
# database only allows int4 entries for min and max. For fiat currencies,
# we multiply by data.fiat_base_multiplier (usually 100) to save the value in cents.
@ -140,19 +140,21 @@ async def api_link_create_or_update(
data.min *= data.fiat_base_multiplier
data.max *= data.fiat_base_multiplier
if data.success_url and data.success_url != "" and not data.success_url.startswith("https://"):
if (
data.success_url
and data.success_url != ""
and not data.success_url.startswith("https://")
):
raise HTTPException(
detail="Success URL must be secure https://...",
status_code=HTTPStatus.BAD_REQUEST,
)
if data.username:
try:
await check_lnaddress_format(data.username)
except AssertionError as ex:
raise HTTPException(
detail=f"Invalid username: {ex}", status_code=HTTPStatus.BAD_REQUEST
)
if data.username and not re.match("^[a-z0-9-_.]{3,64}$", data.username):
raise HTTPException(
detail=f"Invalid username: {data.username}",
status_code=HTTPStatus.BAD_REQUEST,
)
# if wallet is not provided, use the wallet of the key
if not data.wallet:
@ -191,7 +193,7 @@ async def api_link_create_or_update(
return {**link.dict(), "lnurl": link.lnurl(request)}
@lnurlp_ext.delete("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
@lnurlp_api_router.delete("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
async def api_link_delete(link_id: str, wallet: WalletTypeInfo = Depends(get_key_type)):
link = await get_pay_link(link_id)
@ -209,7 +211,7 @@ async def api_link_delete(link_id: str, wallet: WalletTypeInfo = Depends(get_key
return {"success": True}
@lnurlp_ext.get("/api/v1/rate/{currency}", status_code=HTTPStatus.OK)
@lnurlp_api_router.get("/api/v1/rate/{currency}", status_code=HTTPStatus.OK)
async def api_check_fiat_rate(currency):
try:
rate = await get_fiat_rate_satoshis(currency)
@ -219,22 +221,22 @@ async def api_check_fiat_rate(currency):
return {"rate": rate}
@lnurlp_ext.get("/api/v1/settings", dependencies=[Depends(check_admin)])
@lnurlp_api_router.get("/api/v1/settings", dependencies=[Depends(check_admin)])
async def api_get_or_create_settings() -> LnurlpSettings:
return await get_or_create_lnurlp_settings()
@lnurlp_ext.put("/api/v1/settings", dependencies=[Depends(check_admin)])
@lnurlp_api_router.put("/api/v1/settings", dependencies=[Depends(check_admin)])
async def api_update_settings(data: LnurlpSettings) -> LnurlpSettings:
try:
parse_nostr_private_key(data.nostr_private_key)
except Exception:
except Exception as exc:
raise HTTPException(
detail="Invalid Nostr private key.", status_code=HTTPStatus.BAD_REQUEST
)
) from exc
return await update_lnurlp_settings(data)
@lnurlp_ext.delete("/api/v1/settings", dependencies=[Depends(check_admin)])
@lnurlp_api_router.delete("/api/v1/settings", dependencies=[Depends(check_admin)])
async def api_delete_settings() -> None:
await delete_lnurlp_settings()