2022-08-14 23:52:55 +02:00
|
|
|
Vue.component(VueQrcode.name, VueQrcode)
|
|
|
|
|
|
|
|
const mapCards = obj => {
|
|
|
|
obj.date = Quasar.utils.date.formatDate(
|
|
|
|
new Date(obj.time * 1000),
|
|
|
|
'YYYY-MM-DD HH:mm'
|
|
|
|
)
|
|
|
|
|
|
|
|
return obj
|
|
|
|
}
|
|
|
|
|
|
|
|
new Vue({
|
|
|
|
el: '#vue',
|
|
|
|
mixins: [windowMixin],
|
|
|
|
data: function () {
|
2022-08-29 14:18:18 +01:00
|
|
|
return {
|
2022-08-22 20:14:19 +01:00
|
|
|
toggleAdvanced: false,
|
2022-08-28 10:58:17 +01:00
|
|
|
nfcTagReading: false,
|
2022-08-29 08:49:04 -06:00
|
|
|
lnurlLink: `${window.location.host}/boltcards/api/v1/scan/`,
|
2022-08-14 23:52:55 +02:00
|
|
|
cards: [],
|
|
|
|
hits: [],
|
2022-08-24 09:33:38 +01:00
|
|
|
refunds: [],
|
2022-08-14 23:52:55 +02:00
|
|
|
cardDialog: {
|
|
|
|
show: false,
|
2022-08-22 22:33:20 +01:00
|
|
|
data: {
|
2022-08-29 14:18:18 +01:00
|
|
|
counter: 1,
|
2022-08-22 22:33:20 +01:00
|
|
|
k0: '',
|
|
|
|
k1: '',
|
|
|
|
k2: '',
|
2022-08-29 15:11:25 +01:00
|
|
|
uid: '',
|
2022-08-29 14:18:18 +01:00
|
|
|
card_name: ''
|
|
|
|
},
|
2022-08-14 23:52:55 +02:00
|
|
|
temp: {}
|
|
|
|
},
|
|
|
|
cardsTable: {
|
|
|
|
columns: [
|
|
|
|
{
|
|
|
|
name: 'card_name',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Card name',
|
|
|
|
field: 'card_name'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'counter',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Counter',
|
|
|
|
field: 'counter'
|
|
|
|
},
|
|
|
|
{
|
2022-08-28 12:16:23 +01:00
|
|
|
name: 'wallet',
|
2022-08-14 23:52:55 +02:00
|
|
|
align: 'left',
|
2022-08-28 12:16:23 +01:00
|
|
|
label: 'Wallet',
|
|
|
|
field: 'wallet'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'tx_limit',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Max tx',
|
|
|
|
field: 'tx_limit'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'daily_limit',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Daily tx limit',
|
|
|
|
field: 'daily_limit'
|
2022-08-14 23:52:55 +02:00
|
|
|
}
|
|
|
|
],
|
|
|
|
pagination: {
|
|
|
|
rowsPerPage: 10
|
|
|
|
}
|
|
|
|
},
|
2022-08-22 23:29:42 +01:00
|
|
|
refundsTable: {
|
|
|
|
columns: [
|
|
|
|
{
|
|
|
|
name: 'hit_id',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Hit ID',
|
|
|
|
field: 'hit_id'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'refund_amount',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Refund Amount',
|
2022-08-27 17:26:17 +01:00
|
|
|
field: 'refund_amount'
|
2022-08-22 23:29:42 +01:00
|
|
|
},
|
|
|
|
{
|
2022-08-29 09:32:13 -06:00
|
|
|
name: 'date',
|
2022-08-22 23:29:42 +01:00
|
|
|
align: 'left',
|
|
|
|
label: 'Time',
|
2022-08-29 09:32:13 -06:00
|
|
|
field: 'date'
|
2022-08-22 23:29:42 +01:00
|
|
|
}
|
|
|
|
],
|
|
|
|
pagination: {
|
|
|
|
rowsPerPage: 10,
|
|
|
|
sortBy: 'date',
|
|
|
|
descending: true
|
|
|
|
}
|
|
|
|
},
|
2022-08-14 23:52:55 +02:00
|
|
|
hitsTable: {
|
|
|
|
columns: [
|
|
|
|
{
|
|
|
|
name: 'card_name',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Card name',
|
|
|
|
field: 'card_name'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'old_ctr',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Old counter',
|
|
|
|
field: 'old_ctr'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'new_ctr',
|
|
|
|
align: 'left',
|
|
|
|
label: 'New counter',
|
|
|
|
field: 'new_ctr'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'date',
|
|
|
|
align: 'left',
|
|
|
|
label: 'Time',
|
|
|
|
field: 'date'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'ip',
|
|
|
|
align: 'left',
|
|
|
|
label: 'IP',
|
|
|
|
field: 'ip'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'useragent',
|
|
|
|
align: 'left',
|
|
|
|
label: 'User agent',
|
|
|
|
field: 'useragent'
|
|
|
|
}
|
|
|
|
],
|
|
|
|
pagination: {
|
|
|
|
rowsPerPage: 10,
|
|
|
|
sortBy: 'date',
|
|
|
|
descending: true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
qrCodeDialog: {
|
|
|
|
show: false,
|
|
|
|
data: null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
2022-08-29 15:11:25 +01:00
|
|
|
readNfcTag: function () {
|
|
|
|
try {
|
|
|
|
const self = this
|
|
|
|
|
|
|
|
if (typeof NDEFReader == 'undefined') {
|
|
|
|
throw {
|
|
|
|
toString: function () {
|
|
|
|
return 'NFC not supported on this device or browser.'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const ndef = new NDEFReader()
|
|
|
|
|
|
|
|
const readerAbortController = new AbortController()
|
|
|
|
readerAbortController.signal.onabort = event => {
|
|
|
|
console.log('All NFC Read operations have been aborted.')
|
|
|
|
}
|
|
|
|
|
|
|
|
this.nfcTagReading = true
|
|
|
|
this.$q.notify({
|
|
|
|
message: 'Tap your NFC tag to pay this invoice with LNURLw.'
|
|
|
|
})
|
|
|
|
|
|
|
|
return ndef.scan({signal: readerAbortController.signal}).then(() => {
|
|
|
|
ndef.onreadingerror = () => {
|
|
|
|
self.nfcTagReading = false
|
|
|
|
|
|
|
|
this.$q.notify({
|
|
|
|
type: 'negative',
|
|
|
|
message: 'There was an error reading this NFC tag.'
|
|
|
|
})
|
|
|
|
|
|
|
|
readerAbortController.abort()
|
|
|
|
}
|
|
|
|
|
|
|
|
ndef.onreading = ({message, serialNumber}) => {
|
|
|
|
//Decode NDEF data from tag
|
|
|
|
var self = this
|
|
|
|
self.cardDialog.data.uid = serialNumber
|
|
|
|
.toUpperCase()
|
|
|
|
.replaceAll(':', '')
|
|
|
|
this.$q.notify({
|
|
|
|
type: 'positive',
|
|
|
|
message: 'NFC tag read successfully.'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} catch (error) {
|
|
|
|
this.nfcTagReading = false
|
|
|
|
this.$q.notify({
|
|
|
|
type: 'negative',
|
|
|
|
message: error
|
|
|
|
? error.toString()
|
|
|
|
: 'An unexpected error has occurred.'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2022-08-14 23:52:55 +02:00
|
|
|
getCards: function () {
|
|
|
|
var self = this
|
|
|
|
|
|
|
|
LNbits.api
|
|
|
|
.request(
|
|
|
|
'GET',
|
|
|
|
'/boltcards/api/v1/cards?all_wallets=true',
|
2022-08-27 17:26:17 +01:00
|
|
|
this.g.user.wallets[0].inkey
|
2022-08-14 23:52:55 +02:00
|
|
|
)
|
|
|
|
.then(function (response) {
|
|
|
|
self.cards = response.data.map(function (obj) {
|
|
|
|
return mapCards(obj)
|
|
|
|
})
|
|
|
|
})
|
2022-08-29 09:33:28 -06:00
|
|
|
.then(function () {
|
|
|
|
self.getHits()
|
|
|
|
})
|
2022-08-14 23:52:55 +02:00
|
|
|
},
|
|
|
|
getHits: function () {
|
|
|
|
var self = this
|
|
|
|
LNbits.api
|
|
|
|
.request(
|
|
|
|
'GET',
|
|
|
|
'/boltcards/api/v1/hits?all_wallets=true',
|
|
|
|
this.g.user.wallets[0].inkey
|
|
|
|
)
|
|
|
|
.then(function (response) {
|
|
|
|
self.hits = response.data.map(function (obj) {
|
|
|
|
obj.card_name = self.cards.find(d => d.id == obj.card_id).card_name
|
|
|
|
return mapCards(obj)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
2022-08-24 09:33:38 +01:00
|
|
|
getRefunds: function () {
|
|
|
|
var self = this
|
|
|
|
LNbits.api
|
|
|
|
.request(
|
|
|
|
'GET',
|
|
|
|
'/boltcards/api/v1/refunds?all_wallets=true',
|
|
|
|
this.g.user.wallets[0].inkey
|
|
|
|
)
|
|
|
|
.then(function (response) {
|
|
|
|
self.refunds = response.data.map(function (obj) {
|
|
|
|
return mapCards(obj)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
2022-08-29 08:51:32 -06:00
|
|
|
openQrCodeDialog(cardId) {
|
2022-08-14 23:52:55 +02:00
|
|
|
var card = _.findWhere(this.cards, {id: cardId})
|
|
|
|
this.qrCodeDialog.data = {
|
|
|
|
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
|
|
|
|
name: card.card_name,
|
|
|
|
uid: card.uid,
|
|
|
|
k0: card.k0,
|
|
|
|
k1: card.k1,
|
|
|
|
k2: card.k2
|
|
|
|
}
|
|
|
|
this.qrCodeDialog.show = true
|
|
|
|
},
|
2022-08-24 09:33:38 +01:00
|
|
|
addCardOpen: function () {
|
2022-08-22 22:33:20 +01:00
|
|
|
this.cardDialog.show = true
|
2022-08-26 19:22:03 +01:00
|
|
|
this.generateKeys()
|
2022-08-24 09:33:38 +01:00
|
|
|
},
|
|
|
|
generateKeys: function () {
|
2022-08-28 10:58:17 +01:00
|
|
|
var self = this
|
2022-08-14 23:52:55 +02:00
|
|
|
const genRanHex = size =>
|
|
|
|
[...Array(size)]
|
|
|
|
.map(() => Math.floor(Math.random() * 16).toString(16))
|
|
|
|
.join('')
|
|
|
|
|
|
|
|
debugcard =
|
|
|
|
typeof this.cardDialog.data.card_name === 'string' &&
|
|
|
|
this.cardDialog.data.card_name.search('debug') > -1
|
|
|
|
|
2022-08-29 14:18:18 +01:00
|
|
|
self.cardDialog.data.k0 = debugcard
|
2022-08-14 23:52:55 +02:00
|
|
|
? '11111111111111111111111111111111'
|
|
|
|
: genRanHex(32)
|
|
|
|
|
2022-08-28 10:58:17 +01:00
|
|
|
self.cardDialog.data.k1 = debugcard
|
2022-08-14 23:52:55 +02:00
|
|
|
? '22222222222222222222222222222222'
|
|
|
|
: genRanHex(32)
|
|
|
|
|
2022-08-28 10:58:17 +01:00
|
|
|
self.cardDialog.data.k2 = debugcard
|
2022-08-14 23:52:55 +02:00
|
|
|
? '33333333333333333333333333333333'
|
|
|
|
: genRanHex(32)
|
|
|
|
},
|
|
|
|
closeFormDialog: function () {
|
|
|
|
this.cardDialog.data = {}
|
|
|
|
},
|
|
|
|
sendFormData: function () {
|
|
|
|
let wallet = _.findWhere(this.g.user.wallets, {
|
|
|
|
id: this.cardDialog.data.wallet
|
|
|
|
})
|
|
|
|
let data = this.cardDialog.data
|
|
|
|
if (data.id) {
|
|
|
|
this.updateCard(wallet, data)
|
|
|
|
} else {
|
|
|
|
this.createCard(wallet, data)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
createCard: function (wallet, data) {
|
|
|
|
var self = this
|
|
|
|
|
|
|
|
LNbits.api
|
|
|
|
.request('POST', '/boltcards/api/v1/cards', wallet.adminkey, data)
|
|
|
|
.then(function (response) {
|
|
|
|
self.cards.push(mapCards(response.data))
|
|
|
|
self.cardDialog.show = false
|
|
|
|
self.cardDialog.data = {}
|
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
LNbits.utils.notifyApiError(error)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
updateCardDialog: function (formId) {
|
|
|
|
var card = _.findWhere(this.cards, {id: formId})
|
|
|
|
this.cardDialog.data = _.clone(card)
|
|
|
|
|
|
|
|
this.cardDialog.temp.k0 = this.cardDialog.data.k0
|
|
|
|
this.cardDialog.temp.k1 = this.cardDialog.data.k1
|
|
|
|
this.cardDialog.temp.k2 = this.cardDialog.data.k2
|
|
|
|
|
|
|
|
this.cardDialog.show = true
|
|
|
|
},
|
|
|
|
updateCard: function (wallet, data) {
|
|
|
|
var self = this
|
|
|
|
|
|
|
|
if (
|
|
|
|
this.cardDialog.temp.k0 != data.k0 ||
|
|
|
|
this.cardDialog.temp.k1 != data.k1 ||
|
|
|
|
this.cardDialog.temp.k2 != data.k2
|
|
|
|
) {
|
|
|
|
data.prev_k0 = this.cardDialog.temp.k0
|
|
|
|
data.prev_k1 = this.cardDialog.temp.k1
|
|
|
|
data.prev_k2 = this.cardDialog.temp.k2
|
|
|
|
}
|
|
|
|
|
|
|
|
LNbits.api
|
|
|
|
.request(
|
|
|
|
'PUT',
|
|
|
|
'/boltcards/api/v1/cards/' + data.id,
|
|
|
|
wallet.adminkey,
|
|
|
|
data
|
|
|
|
)
|
|
|
|
.then(function (response) {
|
|
|
|
self.cards = _.reject(self.cards, function (obj) {
|
|
|
|
return obj.id == data.id
|
|
|
|
})
|
|
|
|
self.cards.push(mapCards(response.data))
|
|
|
|
self.cardDialog.show = false
|
|
|
|
self.cardDialog.data = {}
|
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
LNbits.utils.notifyApiError(error)
|
|
|
|
})
|
|
|
|
},
|
2022-08-28 10:58:17 +01:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
},
|
2022-08-14 23:52:55 +02:00
|
|
|
deleteCard: function (cardId) {
|
|
|
|
let self = this
|
|
|
|
let cards = _.findWhere(this.cards, {id: cardId})
|
|
|
|
|
|
|
|
LNbits.utils
|
|
|
|
.confirmDialog('Are you sure you want to delete this card')
|
|
|
|
.onOk(function () {
|
|
|
|
LNbits.api
|
|
|
|
.request(
|
|
|
|
'DELETE',
|
|
|
|
'/boltcards/api/v1/cards/' + cardId,
|
|
|
|
_.findWhere(self.g.user.wallets, {id: cards.wallet}).adminkey
|
|
|
|
)
|
|
|
|
.then(function (response) {
|
|
|
|
self.cards = _.reject(self.cards, function (obj) {
|
|
|
|
return obj.id == cardId
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
LNbits.utils.notifyApiError(error)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
exportCardsCSV: function () {
|
|
|
|
LNbits.utils.exportCSV(this.cardsTable.columns, this.cards)
|
2022-08-27 17:26:17 +01:00
|
|
|
},
|
|
|
|
exportHitsCSV: function () {
|
|
|
|
LNbits.utils.exportCSV(this.hitsTable.columns, this.hits)
|
|
|
|
},
|
|
|
|
exportRefundsCSV: function () {
|
|
|
|
LNbits.utils.exportCSV(this.refundsTable.columns, this.refunds)
|
2022-08-29 14:18:18 +01:00
|
|
|
}
|
2022-08-14 23:52:55 +02:00
|
|
|
},
|
|
|
|
created: function () {
|
|
|
|
if (this.g.user.wallets.length) {
|
|
|
|
this.getCards()
|
2022-08-24 09:33:38 +01:00
|
|
|
this.getRefunds()
|
2022-08-14 23:52:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|