mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-25 15:10:41 +01:00
162 lines
5 KiB
Python
162 lines
5 KiB
Python
|
# views_api.py is for you API endpoints that could be hit by another service
|
||
|
|
||
|
# add your dependencies here
|
||
|
|
||
|
# import httpx
|
||
|
# (use httpx just like requests, except instead of response.ok there's only the
|
||
|
# response.is_error that is its inverse)
|
||
|
|
||
|
from http import HTTPStatus
|
||
|
|
||
|
from fastapi.params import Depends, Query
|
||
|
from starlette.exceptions import HTTPException
|
||
|
from starlette.requests import Request
|
||
|
|
||
|
from lnbits.core.crud import get_user
|
||
|
from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key
|
||
|
from lnbits.extensions.withdraw import get_withdraw_link
|
||
|
|
||
|
from . import boltcards_ext
|
||
|
from .nxp424 import decryptSUN, getSunMAC
|
||
|
from .crud import (
|
||
|
get_all_cards,
|
||
|
get_cards,
|
||
|
get_card,
|
||
|
create_card,
|
||
|
update_card,
|
||
|
delete_card,
|
||
|
update_card_counter
|
||
|
)
|
||
|
from .models import CreateCardData
|
||
|
|
||
|
@boltcards_ext.get("/api/v1/cards")
|
||
|
async def api_cards(
|
||
|
g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
|
||
|
):
|
||
|
wallet_ids = [g.wallet.id]
|
||
|
|
||
|
if all_wallets:
|
||
|
wallet_ids = (await get_user(g.wallet.user)).wallet_ids
|
||
|
|
||
|
return [card.dict() for card in await get_cards(wallet_ids)]
|
||
|
|
||
|
@boltcards_ext.post("/api/v1/cards", status_code=HTTPStatus.CREATED)
|
||
|
@boltcards_ext.put("/api/v1/cards/{card_id}", status_code=HTTPStatus.OK)
|
||
|
async def api_link_create_or_update(
|
||
|
req: Request,
|
||
|
data: CreateCardData,
|
||
|
card_id: str = None,
|
||
|
wallet: WalletTypeInfo = Depends(require_admin_key),
|
||
|
):
|
||
|
'''
|
||
|
if data.uses > 250:
|
||
|
raise HTTPException(
|
||
|
detail="250 uses max.", status_code=HTTPStatus.BAD_REQUEST
|
||
|
)
|
||
|
|
||
|
if data.min_withdrawable < 1:
|
||
|
raise HTTPException(
|
||
|
detail="Min must be more than 1.", status_code=HTTPStatus.BAD_REQUEST
|
||
|
)
|
||
|
|
||
|
if data.max_withdrawable < data.min_withdrawable:
|
||
|
raise HTTPException(
|
||
|
detail="`max_withdrawable` needs to be at least `min_withdrawable`.",
|
||
|
status_code=HTTPStatus.BAD_REQUEST,
|
||
|
)
|
||
|
'''
|
||
|
if card_id:
|
||
|
card = await get_card(card_id)
|
||
|
if not card:
|
||
|
raise HTTPException(
|
||
|
detail="Card does not exist.", status_code=HTTPStatus.NOT_FOUND
|
||
|
)
|
||
|
if card.wallet != wallet.wallet.id:
|
||
|
raise HTTPException(
|
||
|
detail="Not your card.", status_code=HTTPStatus.FORBIDDEN
|
||
|
)
|
||
|
card = await update_card(
|
||
|
card_id, **data.dict()
|
||
|
)
|
||
|
else:
|
||
|
card = await create_card(
|
||
|
wallet_id=wallet.wallet.id, data=data
|
||
|
)
|
||
|
return card.dict()
|
||
|
|
||
|
@boltcards_ext.delete("/api/v1/cards/{card_id}")
|
||
|
async def api_link_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
|
||
|
card = await get_card(card_id)
|
||
|
|
||
|
if not card:
|
||
|
raise HTTPException(
|
||
|
detail="Card does not exist.", status_code=HTTPStatus.NOT_FOUND
|
||
|
)
|
||
|
|
||
|
if card.wallet != wallet.wallet.id:
|
||
|
raise HTTPException(
|
||
|
detail="Not your card.", status_code=HTTPStatus.FORBIDDEN
|
||
|
)
|
||
|
|
||
|
await delete_card(card_id)
|
||
|
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
|
||
|
|
||
|
@boltcards_ext.get("/api/v1/scan/") # pay.btcslovnik.cz/boltcards/api/v1/scan/?uid=00000000000000&ctr=000000&c=0000000000000000
|
||
|
async def api_scan(
|
||
|
uid, ctr, c,
|
||
|
request: Request
|
||
|
):
|
||
|
card = await get_card(uid, id_is_uid=True)
|
||
|
|
||
|
if card == None:
|
||
|
return {"status": "ERROR", "reason": "Unknown card."}
|
||
|
|
||
|
if c != getSunMAC(bytes.fromhex(uid), bytes.fromhex(ctr)[::-1], bytes.fromhex(card.file_key)).hex().upper():
|
||
|
print(c)
|
||
|
print(getSunMAC(bytes.fromhex(uid), bytes.fromhex(ctr)[::-1], bytes.fromhex(card.file_key)).hex().upper())
|
||
|
return {"status": "ERROR", "reason": "CMAC does not check."}
|
||
|
|
||
|
ctr_int = int(ctr, 16)
|
||
|
|
||
|
if ctr_int <= card.counter:
|
||
|
return {"status": "ERROR", "reason": "This link is already used."}
|
||
|
|
||
|
await update_card_counter(ctr_int, card.id)
|
||
|
|
||
|
link = await get_withdraw_link(card.withdraw, 0)
|
||
|
|
||
|
return link.lnurl_response(request)
|
||
|
|
||
|
@boltcards_ext.get("/api/v1/scane/")
|
||
|
async def api_scane(
|
||
|
e, c,
|
||
|
request: Request
|
||
|
):
|
||
|
card = None
|
||
|
counter = b''
|
||
|
|
||
|
for cand in await get_all_cards():
|
||
|
if cand.meta_key:
|
||
|
card_uid, counter = decryptSUN(bytes.fromhex(e), bytes.fromhex(cand.meta_key))
|
||
|
|
||
|
if card_uid.hex().upper() == cand.uid:
|
||
|
card = cand
|
||
|
break
|
||
|
|
||
|
if card == None:
|
||
|
return {"status": "ERROR", "reason": "Unknown card."}
|
||
|
|
||
|
if c != getSunMAC(card_uid, counter, bytes.fromhex(card.file_key)).hex().upper():
|
||
|
print(c)
|
||
|
print(getSunMAC(card_uid, counter, bytes.fromhex(card.file_key)).hex().upper())
|
||
|
return {"status": "ERROR", "reason": "CMAC does not check."}
|
||
|
|
||
|
counter_int = int.from_bytes(counter, "little")
|
||
|
if counter_int <= card.counter:
|
||
|
return {"status": "ERROR", "reason": "This link is already used."}
|
||
|
|
||
|
await update_card_counter(counter_int, card.id)
|
||
|
|
||
|
link = await get_withdraw_link(card.withdraw, 0)
|
||
|
return link.lnurl_response(request)
|