From 4de7c1a4c00e0253ae84918368d2fce9c2472cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Sun, 31 Mar 2024 10:48:55 +0200 Subject: [PATCH] refactor: do not validate username inside crud check username on api level not inside crud. adds better error reporting for the api user also in frontend --- crud.py | 19 ++++--------------- views_api.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/crud.py b/crud.py index d656e80..f30fd1b 100644 --- a/crud.py +++ b/crud.py @@ -5,7 +5,6 @@ from lnbits.helpers import urlsafe_short_hash, insert_query, update_query from . import db from .models import CreatePayLinkData, LnurlpSettings, PayLink from .nostr.key import PrivateKey -from .services import check_lnaddress_format async def get_or_create_lnurlp_settings() -> LnurlpSettings: @@ -33,21 +32,14 @@ async def delete_lnurlp_settings() -> None: await db.execute("DELETE FROM lnurlp.settings") -async def check_lnaddress_not_exists(username: str) -> bool: - # check if lnaddress username exists in the database when creating a new entry - row = await db.fetchall( - "SELECT username FROM lnurlp.pay_links WHERE username = ?", (username,) +async def get_pay_link_by_username(username: str) -> Optional[PayLink]: + row = await db.fetchone( + "SELECT * FROM lnurlp.pay_links WHERE username = ?", (username,) ) - if row: - raise Exception("Username already exists. Try a different one.") - else: - return True + return PayLink.from_row(row) if row else None async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink: - if data.username: - await check_lnaddress_format(data.username) - await check_lnaddress_not_exists(data.username) link_id = urlsafe_short_hash()[:6] @@ -128,9 +120,6 @@ async def get_pay_links(wallet_ids: Union[str, List[str]]) -> List[PayLink]: async def update_pay_link(link_id: str, **kwargs) -> Optional[PayLink]: - if "username" in kwargs and len(kwargs["username"] or "") > 0: - await check_lnaddress_format(kwargs["username"]) - await check_lnaddress_not_exists(kwargs["username"]) q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) await db.execute( diff --git a/views_api.py b/views_api.py index b3dd01d..aa6da78 100644 --- a/views_api.py +++ b/views_api.py @@ -18,10 +18,12 @@ from .crud import ( get_address_data, get_or_create_lnurlp_settings, get_pay_link, + get_pay_link_by_username, get_pay_links, 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 @@ -84,6 +86,14 @@ async def api_link_retrieve( return {**link.dict(), **{"lnurl": link.lnurl(r)}} +async def check_username_exists(username: str): + prev_link = await get_pay_link_by_username(username) + if prev_link: + raise HTTPException( + detail="Username already taken.", + 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) async def api_link_create_or_update( @@ -134,6 +144,14 @@ async def api_link_create_or_update( 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 link_id: link = await get_pay_link(link_id) @@ -147,9 +165,16 @@ async def api_link_create_or_update( detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN ) + if data.username and data.username != link.username: + await check_username_exists(data.username) + link = await update_pay_link(**data.dict(), link_id=link_id) else: + if data.username: + await check_username_exists(data.username) + link = await create_pay_link(data, wallet_id=wallet.wallet.id) + assert link return {**link.dict(), "lnurl": link.lnurl(request)}