Added enable disable card

This commit is contained in:
ben 2022-08-28 10:58:17 +01:00
parent 20dbd879b1
commit 977f9bb8c4
7 changed files with 92 additions and 14 deletions

View file

@ -19,12 +19,13 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
counter,
tx_limit,
daily_limit,
enable,
k0,
k1,
k2,
otp
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
card_id,
@ -34,6 +35,7 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
data.counter,
data.tx_limit,
data.daily_limit,
True,
data.k0,
data.k1,
data.k2,
@ -104,7 +106,17 @@ async def get_card_by_otp(otp: str) -> Optional[Card]:
async def delete_card(card_id: str) -> None:
# Delete cards
card = await get_card(card_id)
await db.execute("DELETE FROM boltcards.cards WHERE id = ?", (card_id,))
# Delete hits
hits = await get_hits([card_id])
for hit in hits:
await db.execute("DELETE FROM boltcards.hits WHERE id = ?", (hit.id,))
# Delete refunds
refunds = await get_refunds([hit])
for refund in refunds:
await db.execute("DELETE FROM boltcards.refunds WHERE id = ?", (refund.hit_id,))
async def update_card_counter(counter: int, id: str):
@ -113,6 +125,12 @@ async def update_card_counter(counter: int, id: str):
(counter, id),
)
async def enable_disable_card(enable: bool, id: str) -> Optional[Card]:
row = await db.execute(
"UPDATE boltcards.cards SET enable = ? WHERE id = ?",
(enable, id),
)
return await get_card(id)
async def update_card_otp(otp: str, id: str):
await db.execute(

View file

@ -57,6 +57,8 @@ async def api_scan(p, c, request: Request, card_id: str = None):
try:
card = await get_card_by_uid(card_uid)
if not card.enable:
return {"status": "ERROR", "reason": "Card is disabled."}
card_uid, counter = decryptSUN(bytes.fromhex(p), bytes.fromhex(card.k1))
if card.uid.upper() != card_uid.hex().upper():
return {"status": "ERROR", "reason": "Card UID mis-match."}
@ -173,6 +175,8 @@ async def lnurlp_response(req: Request, hit_id: str = Query(None)):
card = await get_card(hit.card_id)
if not hit:
return {"status": "ERROR", "reason": f"LNURL-pay record not found."}
if not card.enable:
return {"status": "ERROR", "reason": "Card is disabled."}
payResponse = {
"tag": "payRequest",
"callback": req.url_for("boltcards.lnurlp_callback", hit_id=hit_id),

View file

@ -12,6 +12,7 @@ async def m001_initial(db):
counter INT NOT NULL DEFAULT 0,
tx_limit TEXT NOT NULL,
daily_limit TEXT NOT NULL,
enable BOOL NOT NULL,
k0 TEXT NOT NULL DEFAULT '00000000000000000000000000000000',
k1 TEXT NOT NULL DEFAULT '00000000000000000000000000000000',
k2 TEXT NOT NULL DEFAULT '00000000000000000000000000000000',

View file

@ -22,6 +22,7 @@ class Card(BaseModel):
counter: int
tx_limit: int
daily_limit: int
enable: bool
k0: str
k1: str
k2: str
@ -49,6 +50,7 @@ class CreateCardData(BaseModel):
counter: int = Query(0)
tx_limit: int = Query(0)
daily_limit: int = Query(0)
enable: bool = Query(...)
k0: str = Query(ZERO_KEY)
k1: str = Query(ZERO_KEY)
k2: str = Query(ZERO_KEY)

View file

@ -16,6 +16,7 @@ new Vue({
data: function () {
return {
toggleAdvanced: false,
nfcTagReading: false,
cards: [],
hits: [],
refunds: [],
@ -194,6 +195,7 @@ new Vue({
this.generateKeys()
},
generateKeys: function () {
var self = this
const genRanHex = size =>
[...Array(size)]
.map(() => Math.floor(Math.random() * 16).toString(16))
@ -203,20 +205,17 @@ new Vue({
typeof this.cardDialog.data.card_name === 'string' &&
this.cardDialog.data.card_name.search('debug') > -1
this.cardDialog.data.k0 = debugcard
self.cardDialog.data.k0 = debugcard
? '11111111111111111111111111111111'
: genRanHex(32)
this.$refs['k0'].value = this.cardDialog.data.k0
this.cardDialog.data.k1 = debugcard
self.cardDialog.data.k1 = debugcard
? '22222222222222222222222222222222'
: genRanHex(32)
this.$refs['k1'].value = this.cardDialog.data.k1
this.cardDialog.data.k2 = debugcard
self.cardDialog.data.k2 = debugcard
? '33333333333333333333333333333333'
: genRanHex(32)
this.$refs['k2'].value = this.cardDialog.data.k2
},
closeFormDialog: function () {
this.cardDialog.data = {}
@ -288,6 +287,28 @@ new Vue({
LNbits.utils.notifyApiError(error)
})
},
enableCard: function (wallet, card_id, enable) {
var self = this
let fullWallet = _.findWhere(self.g.user.wallets, {
id: wallet
})
LNbits.api
.request(
'GET',
'/boltcards/api/v1/cards/enable/' + card_id + '/' + enable,
fullWallet.adminkey
)
.then(function (response) {
console.log(response.data)
self.cards = _.reject(self.cards, function (obj) {
return obj.id == response.data.id
})
self.cards.push(mapCards(response.data))
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
})
},
deleteCard: function (cardId) {
let self = this
let cards = _.findWhere(this.cards, {id: cardId})

View file

@ -65,6 +65,20 @@
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ 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>
</q-td>
<q-td auto-width>
<q-btn
flat
@ -73,8 +87,7 @@
@click="updateCardDialog(props.row.id)"
icon="edit"
color="light-blue"
>
</q-btn>
><q-tooltip>Edit card</q-tooltip></q-btn>
</q-td>
<q-td auto-width>
<q-btn
@ -84,7 +97,7 @@
@click="deleteCard(props.row.id)"
icon="cancel"
color="pink"
></q-btn>
><q-tooltip>Deleting card will also delete all records</q-tooltip></q-btn>
</q-td>
</q-tr>
</template>
@ -255,7 +268,6 @@
<q-toggle
@click="toggleKeys"
v-model="toggleAdvanced"
label="Show advanced options"
></q-toggle>
@ -263,7 +275,7 @@
<q-input
filled
dense
ref="k0"
v-model.trim="cardDialog.data.k0"
type="text"
label="Card Auth key (K0)"
@ -274,7 +286,7 @@
<q-input
filled
dense
ref="k1"
v-model.trim="cardDialog.data.k1"
type="text"
label="Card Meta key (K1)"
@ -283,7 +295,7 @@
<q-input
filled
dense
ref="k2"
v-model.trim="cardDialog.data.k2"
type="text"
label="Card File key (K2)"

View file

@ -21,6 +21,7 @@ from .crud import (
update_card,
update_card_counter,
update_card_otp,
enable_disable_card,
get_refunds,
)
from .models import CreateCardData
@ -89,6 +90,25 @@ async def api_card_create_or_update(
card = await create_card(wallet_id=wallet.wallet.id, data=data)
return card.dict()
@boltcards_ext.get("/api/v1/cards/enable/{card_id}/{enable}", status_code=HTTPStatus.OK)
async def enable_card(
card_id,
enable,
wallet: WalletTypeInfo = Depends(require_admin_key),
):
card = await get_card(card_id)
if not card:
raise HTTPException(
detail="No card found.", status_code=HTTPStatus.NOT_FOUND
)
if card.wallet != wallet.wallet.id:
raise HTTPException(
detail="Not your card.", status_code=HTTPStatus.FORBIDDEN
)
card = await enable_disable_card(enable=enable, id=card_id)
logger.debug(enable)
logger.debug(card)
return card.dict()
@boltcards_ext.delete("/api/v1/cards/{card_id}")
async def api_card_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)):