Merge branch 'bensbits' into ext-boltcards-2

This commit is contained in:
ben 2022-08-29 15:37:55 +01:00
commit d858a3c7cd
3 changed files with 59 additions and 227 deletions

View file

@ -5,10 +5,10 @@ async def m001_initial(db):
await db.execute(
"""
CREATE TABLE boltcards.cards (
id TEXT PRIMARY KEY,
id TEXT PRIMARY KEY UNIQUE,
wallet TEXT NOT NULL,
card_name TEXT NOT NULL,
uid TEXT NOT NULL,
uid TEXT NOT NULL UNIQUE,
counter INT NOT NULL DEFAULT 0,
tx_limit TEXT NOT NULL,
daily_limit TEXT NOT NULL,
@ -30,7 +30,7 @@ async def m001_initial(db):
await db.execute(
"""
CREATE TABLE boltcards.hits (
id TEXT PRIMARY KEY,
id TEXT PRIMARY KEY UNIQUE,
card_id TEXT NOT NULL,
ip TEXT NOT NULL,
spent BOOL NOT NULL DEFAULT True,
@ -48,7 +48,7 @@ async def m001_initial(db):
await db.execute(
"""
CREATE TABLE boltcards.refunds (
id TEXT PRIMARY KEY,
id TEXT PRIMARY KEY UNIQUE,
hit_id TEXT NOT NULL,
refund_amount INT NOT NULL,
time TIMESTAMP NOT NULL DEFAULT """

View file

@ -12,33 +12,18 @@
<h5 class="text-subtitle1 q-my-none">Cards</h5>
</div>
<div class="col">
<q-btn
round
size="sm"
icon="add"
unelevated
color="primary"
@click="addCardOpen"
>
<q-btn round size="sm" icon="add" unelevated color="primary" @click="addCardOpen">
<q-tooltip>Add card</q-tooltip>
</q-btn>
</div>
</div>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportCardsCSV"
>Export to CSV</q-btn
>
<q-btn flat color="grey" @click="exportCardsCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="cards"
row-key="id"
:columns="cardsTable.columns"
:pagination.sync="cardsTable.pagination"
>
<q-table dense flat :data="cards" row-key="id" :columns="cardsTable.columns"
:pagination.sync="cardsTable.pagination">
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
@ -53,13 +38,8 @@
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
unelevated
dense
icon="qr_code"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.id)"
>
<q-btn unelevated dense icon="qr_code" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.id)">
<q-tooltip>Card key credentials</q-tooltip>
</q-btn>
</q-td>
@ -67,45 +47,19 @@
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.enable"
dense
@click="enableCard(props.row.wallet, props.row.id, false)"
color="pink"
>DISABLE</q-btn
>
<q-btn
v-else
dense
@click="enableCard(props.row.wallet, props.row.id, true)"
color="green"
>ENABLE
<q-btn v-if="props.row.enable" dense @click="enableCard(props.row.wallet, props.row.id, false)"
color="pink">DISABLE</q-btn>
<q-btn v-else dense @click="enableCard(props.row.wallet, props.row.id, true)" color="green">ENABLE
</q-btn>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="updateCardDialog(props.row.id)"
icon="edit"
color="light-blue"
>
<q-btn flat dense size="xs" @click="updateCardDialog(props.row.id)" icon="edit" color="light-blue">
<q-tooltip>Edit card</q-tooltip>
</q-btn>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
size="xs"
@click="deleteCard(props.row.id)"
icon="cancel"
color="pink"
>
<q-tooltip
>Deleting card will also delete all records</q-tooltip
>
<q-btn flat dense size="xs" @click="deleteCard(props.row.id)" icon="cancel" color="pink">
<q-tooltip>Deleting card will also delete all records</q-tooltip>
</q-btn>
</q-td>
</q-tr>
@ -121,19 +75,11 @@
<h5 class="text-subtitle1 q-my-none">Hits</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportCardsCSV"
>Export to CSV</q-btn
>
<q-btn flat color="grey" @click="exportCardsCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="hits"
row-key="id"
:columns="hitsTable.columns"
:pagination.sync="hitsTable.pagination"
>
<q-table dense flat :data="hits" row-key="id" :columns="hitsTable.columns"
:pagination.sync="hitsTable.pagination">
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
@ -160,19 +106,11 @@
<h5 class="text-subtitle1 q-my-none">Refunds</h5>
</div>
<div class="col-auto">
<q-btn flat color="grey" @click="exportRefundsCSV"
>Export to CSV</q-btn
>
<q-btn flat color="grey" @click="exportRefundsCSV">Export to CSV</q-btn>
</div>
</div>
<q-table
dense
flat
:data="refunds"
row-key="id"
:columns="refundsTable.columns"
:pagination.sync="refundsTable.pagination"
>
<q-table dense flat :data="refunds" row-key="id" :columns="refundsTable.columns"
:pagination.sync="refundsTable.pagination">
{% raw %}
<template v-slot:header="props">
<q-tr :props="props">
@ -209,148 +147,55 @@
<q-dialog v-model="cardDialog.show" position="top" @hide="closeFormDialog">
<q-card class="q-pa-lg q-pt-xl lnbits__dialog-card">
<q-form @submit="sendFormData" class="q-gutter-md">
<q-select
filled
dense
emit-value
v-model="cardDialog.data.wallet"
:options="g.user.walletOptions"
label="Wallet *"
>
<q-select filled dense emit-value v-model="cardDialog.data.wallet" :options="g.user.walletOptions"
label="Wallet *">
</q-select>
<div class="row">
<div class="col">
<q-input
filled
dense
emit-value
v-model.trim="cardDialog.data.tx_limit"
type="number"
label="Max transaction (sats)"
class="q-pr-sm"
></q-input>
<q-input filled dense emit-value v-model.trim="cardDialog.data.tx_limit" type="number"
label="Max transaction (sats)" class="q-pr-sm"></q-input>
</div>
<div class="col">
<q-input
filled
dense
emit-value
v-model.trim="cardDialog.data.daily_limit"
type="number"
label="Daily limit (sats)"
></q-input>
<q-input filled dense emit-value v-model.trim="cardDialog.data.daily_limit" type="number"
label="Daily limit (sats)"></q-input>
</div>
</div>
<q-input
filled
dense
emit-value
v-model.trim="cardDialog.data.card_name"
type="text"
label="Card name "
>
<q-input filled dense emit-value v-model.trim="cardDialog.data.card_name" type="text" label="Card name ">
</q-input>
<div class="row">
<div class="col-10">
<q-input
filled
dense
emit-value
v-model.trim="cardDialog.data.uid"
type="text"
label="Card UID "
>
<q-tooltip
>Get from the card you'll use, using an NFC app</q-tooltip
>
<q-input filled dense emit-value v-model.trim="cardDialog.data.uid" type="text" label="Card UID ">
<q-tooltip>Get from the card you'll use, using an NFC app</q-tooltip>
</q-input>
</div>
<div class="col-2 q-pl-sm">
<q-btn
outline
disable
color="grey"
icon="nfc"
:disable="nfcTagReading"
@click="readNfcTag()"
>
<q-btn outline disable color="grey" icon="nfc" :disable="nfcTagReading" @click="readNfcTag()">
<q-tooltip>Tap card to scan UID</q-tooltip>
</q-btn>
</div>
</div>
<q-toggle
v-model="toggleAdvanced"
label="Show advanced options"
></q-toggle>
<q-toggle v-model="toggleAdvanced" label="Show advanced options"></q-toggle>
<div v-show="toggleAdvanced">
<q-input
filled
dense
v-model.trim="cardDialog.data.k0"
type="text"
label="Card Auth key (K0)"
hint="Used to authentificate with the card (16 bytes in HEX). "
@randomkey
>
<q-input filled dense v-model.trim="cardDialog.data.k0" type="text" label="Card Auth key (K0)"
hint="Used to authentificate with the card (16 bytes in HEX). " @randomkey>
</q-input>
<q-input
filled
dense
v-model.trim="cardDialog.data.k1"
type="text"
label="Card Meta key (K1)"
hint="Used for encypting of the message (16 bytes in HEX)."
></q-input>
<q-input
filled
dense
v-model.trim="cardDialog.data.k2"
type="text"
label="Card File key (K2)"
hint="Used for CMAC of the message (16 bytes in HEX)."
>
<q-input filled dense v-model.trim="cardDialog.data.k1" type="text" label="Card Meta key (K1)"
hint="Used for encypting of the message (16 bytes in HEX)."></q-input>
<q-input filled dense v-model.trim="cardDialog.data.k2" type="text" label="Card File key (K2)"
hint="Used for CMAC of the message (16 bytes in HEX).">
</q-input>
<q-input
filled
dense
v-model.number="cardDialog.data.counter"
type="number"
label="Initial counter"
>
<q-tooltip class="bg-grey-8" anchor="bottom left" self="top left"
>Zero if you don't know.</q-tooltip
>
<q-input filled dense v-model.number="cardDialog.data.counter" type="number" label="Initial counter">
<q-tooltip class="bg-grey-8" anchor="bottom left" self="top left">Zero if you don't know.</q-tooltip>
</q-input>
<q-btn
unelevated
color="primary"
class="q-ml-auto"
v-on:click="generateKeys"
v-on:click.right="debugKeys"
v-el:keybtn
>Generate keys</q-btn
>
<q-btn unelevated color="primary" class="q-ml-auto" v-on:click="generateKeys" v-on:click.right="debugKeys"
v-el:keybtn>Generate keys</q-btn>
</div>
<div class="row q-mt-lg">
<q-btn
v-if="cardDialog.data.id"
unelevated
color="primary"
type="submit"
>Update Card</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="cardDialog.data.uid == null"
type="submit"
>Create Card
<q-btn v-if="cardDialog.data.id" unelevated color="primary" type="submit">Update Card</q-btn>
<q-btn v-else unelevated color="primary" :disable="cardDialog.data.uid == null" type="submit">Create Card
</q-btn>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
</div>
</q-form>
</q-card>
@ -360,11 +205,7 @@
<q-card v-if="qrCodeDialog.data" class="q-pa-lg lnbits__dialog-card">
{% raw %}
<q-responsive :ratio="1" class="q-mx-xl q-mb-md">
<qrcode
:value="qrCodeDialog.data.link"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
<qrcode :value="qrCodeDialog.data.link" :options="{width: 800}" class="rounded-borders"></qrcode>
</q-responsive>
<p style="word-break: break-all" class="text-center">
(Keys for bolt-nfc-android-app)
@ -375,27 +216,14 @@
<strong>Lock key:</strong> {{ qrCodeDialog.data.k0 }}<br />
<strong>Meta key:</strong> {{ qrCodeDialog.data.k1 }}<br />
<strong>File key:</strong> {{ qrCodeDialog.data.k2 }}<br />
</p>
<br />
<q-btn
unelevated
outline
color="grey"
@click="copyText(lnurlLink + qrCodeDialog.data.uid)"
label="Base url (LNURL://)"
>
</q-btn>
<q-btn
unelevated
outline
color="grey"
@click="copyText(qrCodeDialog.data.link)"
label="Keys/Auth link"
>
</p><br />
<q-btn unelevated outline color="grey" @click="copyText(lnurlLink + qrCodeDialog.data.uid)" label="Base url (LNURL://)">
</q-btn>
<q-btn unelevated outline color="grey" @click="copyText(qrCodeDialog.data.link)" label="Keys/Auth link">
</q-btn>
<q-tooltip>Click to copy, then add to NFC card</q-tooltip>
{% endraw %}
<div class="row q-mt-lg q-gutter-sm">
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
@ -406,4 +234,4 @@
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script src="/boltcards/static/js/index.js"></script>
{% endblock %}
{% endblock %}

View file

@ -74,7 +74,11 @@ async def api_card_create_or_update(
raise HTTPException(
detail="Invalid byte data provided.", status_code=HTTPStatus.BAD_REQUEST
)
checkUid = await get_card_by_uid(data.uid)
if checkUid:
raise HTTPException(
detail="UID already registered. Delete registered card and try again.", status_code=HTTPStatus.BAD_REQUEST
)
if card_id:
card = await get_card(card_id)
if not card: