feat: deeplinks support (#58)
* feat: deeplinks support * fix: move href logic into compute * chore: fix linting
This commit is contained in:
parent
74e746c9e9
commit
b86263cefa
4 changed files with 72 additions and 1 deletions
|
|
@ -5,7 +5,7 @@ from fastapi import Query, Request
|
||||||
from lnurl import Lnurl
|
from lnurl import Lnurl
|
||||||
from lnurl import encode as lnurl_encode
|
from lnurl import encode as lnurl_encode
|
||||||
from lnurl.types import LnurlPayMetadata
|
from lnurl.types import LnurlPayMetadata
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
ZERO_KEY = "00000000000000000000000000000000"
|
ZERO_KEY = "00000000000000000000000000000000"
|
||||||
|
|
||||||
|
|
@ -71,3 +71,8 @@ class Refund(BaseModel):
|
||||||
hit_id: str
|
hit_id: str
|
||||||
refund_amount: int
|
refund_amount: int
|
||||||
time: datetime
|
time: datetime
|
||||||
|
|
||||||
|
|
||||||
|
class UIDPost(BaseModel):
|
||||||
|
UID: str = Field(None, description="The UID of the card.")
|
||||||
|
LNURLW: str = Field(None, description="The LNURLW of the card.")
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,15 @@ window.app = Vue.createApp({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
deeplinkUrl() {
|
||||||
|
const baseUrl = `boltcard://${this.qrCodeDialog.wipe ? 'reset' : 'program'}`
|
||||||
|
const url =
|
||||||
|
this.qrCodeDialog.data.link +
|
||||||
|
(this.qrCodeDialog.wipe ? '&wipe=true' : '')
|
||||||
|
return `${baseUrl}?url=${encodeURIComponent(url)}`
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
readNfcTag() {
|
readNfcTag() {
|
||||||
const ndef = new NDEFReader()
|
const ndef = new NDEFReader()
|
||||||
|
|
@ -229,6 +238,9 @@ window.app = Vue.createApp({
|
||||||
this.qrCodeDialog.data = {
|
this.qrCodeDialog.data = {
|
||||||
id: card.id,
|
id: card.id,
|
||||||
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
|
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
|
||||||
|
encodedURI: encodeURIComponent(
|
||||||
|
window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp
|
||||||
|
),
|
||||||
name: card.card_name,
|
name: card.card_name,
|
||||||
uid: card.uid,
|
uid: card.uid,
|
||||||
external_id: card.external_id,
|
external_id: card.external_id,
|
||||||
|
|
|
||||||
|
|
@ -463,6 +463,7 @@
|
||||||
<q-tooltip>Click to copy, then paste to NFC Card Creator</q-tooltip>
|
<q-tooltip>Click to copy, then paste to NFC Card Creator</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
class="q-ml-sm"
|
||||||
unelevated
|
unelevated
|
||||||
outline
|
outline
|
||||||
color="red"
|
color="red"
|
||||||
|
|
@ -473,6 +474,17 @@
|
||||||
>
|
>
|
||||||
<q-tooltip>Backup the keys, or wipe the card first!</q-tooltip>
|
<q-tooltip>Backup the keys, or wipe the card first!</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
<q-btn
|
||||||
|
class="q-ml-sm"
|
||||||
|
unelevated
|
||||||
|
outline
|
||||||
|
color="grey"
|
||||||
|
:href="deeplinkUrl"
|
||||||
|
target="_blank"
|
||||||
|
label="Use Boltcard App"
|
||||||
|
>
|
||||||
|
<q-tooltip>Use Boltcard Programmer App</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
<div class="row q-mt-lg q-gutter-sm">
|
<div class="row q-mt-lg q-gutter-sm">
|
||||||
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,14 @@ from .crud import (
|
||||||
get_card,
|
get_card,
|
||||||
get_card_by_external_id,
|
get_card_by_external_id,
|
||||||
get_card_by_otp,
|
get_card_by_otp,
|
||||||
|
get_card_by_uid,
|
||||||
get_hit,
|
get_hit,
|
||||||
get_hits_today,
|
get_hits_today,
|
||||||
spend_hit,
|
spend_hit,
|
||||||
update_card_counter,
|
update_card_counter,
|
||||||
update_card_otp,
|
update_card_otp,
|
||||||
)
|
)
|
||||||
|
from .models import UIDPost
|
||||||
from .nxp424 import decrypt_sun, get_sun_mac
|
from .nxp424 import decrypt_sun, get_sun_mac
|
||||||
|
|
||||||
boltcards_lnurl_router = APIRouter()
|
boltcards_lnurl_router = APIRouter()
|
||||||
|
|
@ -179,6 +181,46 @@ async def api_auth(a, request: Request):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# /boltcards/api/v1/auth?a=00000000000000000000000000000000
|
||||||
|
@boltcards_lnurl_router.post("/api/v1/auth")
|
||||||
|
async def api_auth_post(a: str, request: Request, data: UIDPost, wipe: bool = False):
|
||||||
|
card = None
|
||||||
|
if wipe:
|
||||||
|
card = await get_card_by_otp(a)
|
||||||
|
else:
|
||||||
|
if not data.UID:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="Missing UID.", status_code=HTTPStatus.BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
|
card = await get_card_by_uid(data.UID)
|
||||||
|
if not card:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="Card does not exist.", status_code=HTTPStatus.NOT_FOUND
|
||||||
|
)
|
||||||
|
new_otp = secrets.token_hex(16)
|
||||||
|
await update_card_otp(new_otp, card.id)
|
||||||
|
lnurlw_base = (
|
||||||
|
f"{urlparse(str(request.url)).netloc}/boltcards/api/v1/scan/{card.external_id}"
|
||||||
|
)
|
||||||
|
response = {
|
||||||
|
"CARD_NAME": card.card_name,
|
||||||
|
"ID": str(1),
|
||||||
|
"K0": card.k0,
|
||||||
|
"K1": card.k1,
|
||||||
|
"K2": card.k2,
|
||||||
|
"K3": card.k1,
|
||||||
|
"K4": card.k2,
|
||||||
|
"LNURLW_BASE": "LNURLW://" + lnurlw_base,
|
||||||
|
"LNURLW": "LNURLW://" + lnurlw_base,
|
||||||
|
"PROTOCOL_NAME": "NEW_BOLT_CARD_RESPONSE",
|
||||||
|
"PROTOCOL_VERSION": str(1),
|
||||||
|
}
|
||||||
|
if wipe:
|
||||||
|
response["action"] = "wipe"
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
###############LNURLPAY REFUNDS#################
|
###############LNURLPAY REFUNDS#################
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue