feat: usermanager (#2139)
* feat: usermanager --------- Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -9,6 +9,8 @@ window.localisation.en = {
|
||||
transactions: 'Transactions',
|
||||
dashboard: 'Dashboard',
|
||||
node: 'Node',
|
||||
export_users: 'Export Users',
|
||||
no_users: 'No users found',
|
||||
total_capacity: 'Total Capacity',
|
||||
avg_channel_size: 'Avg. Channel Size',
|
||||
biggest_channel_size: 'Biggest Channel Size',
|
||||
@@ -245,5 +247,6 @@ window.localisation.en = {
|
||||
pay_from_wallet: 'Pay from Wallet',
|
||||
show_qr: 'Show QR',
|
||||
retry_install: 'Retry Install',
|
||||
new_payment: 'Make New Payment'
|
||||
new_payment: 'Make New Payment',
|
||||
hide_empty_wallets: 'Hide empty wallets'
|
||||
}
|
||||
|
||||
@@ -56,9 +56,6 @@ new Vue({
|
||||
'yellow',
|
||||
'orange'
|
||||
],
|
||||
topUpDialog: {
|
||||
show: false
|
||||
},
|
||||
tab: 'funding',
|
||||
needsRestart: false
|
||||
}
|
||||
@@ -80,31 +77,6 @@ new Vue({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addAdminUser() {
|
||||
let addUser = this.formAddAdmin
|
||||
let admin_users = this.formData.lnbits_admin_users
|
||||
if (addUser && addUser.length && !admin_users.includes(addUser)) {
|
||||
//admin_users = [...admin_users, addUser]
|
||||
this.formData.lnbits_admin_users = [...admin_users, addUser]
|
||||
this.formAddAdmin = ''
|
||||
}
|
||||
},
|
||||
removeAdminUser(user) {
|
||||
let admin_users = this.formData.lnbits_admin_users
|
||||
this.formData.lnbits_admin_users = admin_users.filter(u => u !== user)
|
||||
},
|
||||
addAllowedUser() {
|
||||
let addUser = this.formAddUser
|
||||
let allowed_users = this.formData.lnbits_allowed_users
|
||||
if (addUser && addUser.length && !allowed_users.includes(addUser)) {
|
||||
this.formData.lnbits_allowed_users = [...allowed_users, addUser]
|
||||
this.formAddUser = ''
|
||||
}
|
||||
},
|
||||
removeAllowedUser(user) {
|
||||
let allowed_users = this.formData.lnbits_allowed_users
|
||||
this.formData.lnbits_allowed_users = allowed_users.filter(u => u !== user)
|
||||
},
|
||||
addExtensionsManifest() {
|
||||
const addManifest = this.formAddExtensionsManifest.trim()
|
||||
const manifests = this.formData.lnbits_extensions_manifests
|
||||
@@ -200,28 +172,6 @@ new Vue({
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
topupWallet() {
|
||||
LNbits.api
|
||||
.request(
|
||||
'PUT',
|
||||
'/admin/api/v1/topup/',
|
||||
this.g.user.wallets[0].adminkey,
|
||||
this.wallet
|
||||
)
|
||||
.then(response => {
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: this.$t('wallet_topup_ok', {
|
||||
amount: this.wallet.amount
|
||||
}),
|
||||
icon: null
|
||||
})
|
||||
this.wallet = {}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
formatDate(date) {
|
||||
return moment(date * 1000).fromNow()
|
||||
},
|
||||
|
||||
@@ -145,7 +145,7 @@ window.LNbits = {
|
||||
)
|
||||
},
|
||||
updateBalance: function (credit, wallet_id) {
|
||||
return LNbits.api.request('PUT', '/admin/api/v1/topup/', null, {
|
||||
return LNbits.api.request('PUT', '/users/api/v1/topup/', null, {
|
||||
amount: credit,
|
||||
id: wallet_id
|
||||
})
|
||||
|
||||
@@ -170,7 +170,7 @@ Vue.component('lnbits-extension-list', {
|
||||
})
|
||||
|
||||
Vue.component('lnbits-manage', {
|
||||
props: ['showAdmin', 'showNode', 'showExtensions'],
|
||||
props: ['showAdmin', 'showNode', 'showExtensions', 'showUsers'],
|
||||
methods: {
|
||||
isActive: function (path) {
|
||||
return window.location.pathname === path
|
||||
@@ -211,6 +211,14 @@ Vue.component('lnbits-manage', {
|
||||
<q-item-label lines="1" v-text="$t('extensions')"></q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item v-if="showUsers" clickable tag="a" href="/users" :active="isActive('/users')">
|
||||
<q-item-section side>
|
||||
<q-icon name="groups" :color="isActive('/users') ? 'primary' : 'grey-5'" size="md"></q-icon>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" v-text="$t('users')"></q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
`,
|
||||
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
mixins: [windowMixin],
|
||||
data: function () {
|
||||
return {
|
||||
isSuperUser: false,
|
||||
wallet: {},
|
||||
cancel: {},
|
||||
users: [],
|
||||
wallets: [],
|
||||
walletDialog: {
|
||||
show: false
|
||||
},
|
||||
topupDialog: {
|
||||
show: false
|
||||
},
|
||||
createUserDialog: {
|
||||
data: {},
|
||||
fields: [
|
||||
{
|
||||
description: 'Username',
|
||||
name: 'username'
|
||||
},
|
||||
{
|
||||
description: 'Email',
|
||||
name: 'email'
|
||||
},
|
||||
{
|
||||
type: 'password',
|
||||
description: 'Password',
|
||||
name: 'password'
|
||||
}
|
||||
],
|
||||
show: false
|
||||
},
|
||||
createWalletDialog: {
|
||||
data: {},
|
||||
fields: [
|
||||
{
|
||||
type: 'str',
|
||||
description: 'Wallet Name',
|
||||
name: 'name'
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
values: ['', 'EUR', 'USD'],
|
||||
description: 'Currency',
|
||||
name: 'currency'
|
||||
},
|
||||
{
|
||||
type: 'str',
|
||||
description: 'Balance',
|
||||
name: 'balance'
|
||||
}
|
||||
],
|
||||
show: false
|
||||
},
|
||||
walletTable: {
|
||||
columns: [
|
||||
{
|
||||
name: 'name',
|
||||
align: 'left',
|
||||
label: 'Name',
|
||||
field: 'name'
|
||||
},
|
||||
{
|
||||
name: 'currency',
|
||||
align: 'left',
|
||||
label: 'Currency',
|
||||
field: 'currency'
|
||||
},
|
||||
{
|
||||
name: 'balance_msat',
|
||||
align: 'left',
|
||||
label: 'Balance',
|
||||
field: 'balance_msat'
|
||||
},
|
||||
{
|
||||
name: 'deleted',
|
||||
align: 'left',
|
||||
label: 'Deleted',
|
||||
field: 'deleted'
|
||||
}
|
||||
]
|
||||
},
|
||||
usersTable: {
|
||||
columns: [
|
||||
{
|
||||
name: 'balance_msat',
|
||||
align: 'left',
|
||||
label: 'Balance',
|
||||
field: 'balance_msat',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'wallet_count',
|
||||
align: 'left',
|
||||
label: 'Wallet Count',
|
||||
field: 'wallet_count',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'transaction_count',
|
||||
align: 'left',
|
||||
label: 'Transaction Count',
|
||||
field: 'transaction_count',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
align: 'left',
|
||||
label: 'Username',
|
||||
field: 'username',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
align: 'left',
|
||||
label: 'Email',
|
||||
field: 'email',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'last_payment',
|
||||
align: 'left',
|
||||
label: 'Last Payment',
|
||||
field: 'last_payment',
|
||||
sortable: true
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
sortBy: 'balance_msat',
|
||||
rowsPerPage: 10,
|
||||
page: 1,
|
||||
descending: true,
|
||||
rowsNumber: 10
|
||||
},
|
||||
search: null,
|
||||
hideEmpty: true,
|
||||
loading: false
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'usersTable.hideEmpty': function (newVal, _) {
|
||||
if (newVal) {
|
||||
this.usersTable.filter = {
|
||||
'transaction_count[gt]': 0
|
||||
}
|
||||
} else {
|
||||
this.usersTable.filter = {}
|
||||
}
|
||||
this.fetchUsers()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchUsers()
|
||||
},
|
||||
mounted() {
|
||||
this.chart1 = new Chart(this.$refs.chart1.getContext('2d'), {
|
||||
type: 'bubble',
|
||||
options: {
|
||||
layout: {
|
||||
padding: 10
|
||||
}
|
||||
},
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: 'Balance - TX Count in million sats',
|
||||
backgroundColor: 'rgb(255, 99, 132)',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
formatSat: function (value) {
|
||||
return LNbits.utils.formatSat(Math.floor(value / 1000))
|
||||
},
|
||||
usersTableRowKey: function (row) {
|
||||
return row.id
|
||||
},
|
||||
createUser() {
|
||||
LNbits.api
|
||||
.request('POST', '/users/api/v1/user', null, this.createUserDialog.data)
|
||||
.then(() => {
|
||||
this.fetchUsers()
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! User created!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
createWallet(user_id) {
|
||||
LNbits.api
|
||||
.request(
|
||||
'POST',
|
||||
`/users/api/v1/user/${user_id}/wallet`,
|
||||
null,
|
||||
this.createWalletDialog.data
|
||||
)
|
||||
.then(() => {
|
||||
this.fetchUsers()
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! User created!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
deleteUser(user_id) {
|
||||
LNbits.utils
|
||||
.confirmDialog('Are you sure you want to delete this user?')
|
||||
.onOk(() => {
|
||||
LNbits.api
|
||||
.request('DELETE', `/users/api/v1/user/${user_id}`)
|
||||
.then(() => {
|
||||
this.fetchUsers()
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! User deleted!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
undeleteUserWallet(user_id, wallet) {
|
||||
LNbits.api
|
||||
.request(
|
||||
'GET',
|
||||
`/users/api/v1/user/${user_id}/wallet/${wallet}/undelete`
|
||||
)
|
||||
.then(() => {
|
||||
this.fetchWallets(user_id)
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! Undeleted user wallet!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
deleteUserWallet(user_id, wallet, deleted) {
|
||||
const dialogText = deleted
|
||||
? 'Wallet is already deleted, are you sure you want to permanently delete this user wallet?'
|
||||
: 'Are you sure you want to delete this user wallet?'
|
||||
LNbits.utils.confirmDialog(dialogText).onOk(() => {
|
||||
LNbits.api
|
||||
.request('DELETE', `/users/api/v1/user/${user_id}/wallet/${wallet}`)
|
||||
.then(() => {
|
||||
this.fetchWallets(user_id)
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! User wallet deleted!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
updateChart(users) {
|
||||
const filtered = users.filter(user => {
|
||||
if (
|
||||
user.balance_msat === null ||
|
||||
user.balance_msat === 0 ||
|
||||
user.wallet_count === 0
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
const data = filtered.map(user => {
|
||||
return {
|
||||
x: user.transaction_count,
|
||||
y: user.balance_msat / 1000000000,
|
||||
r: 3
|
||||
}
|
||||
})
|
||||
this.chart1.data.datasets[0].data = data
|
||||
this.chart1.update()
|
||||
},
|
||||
fetchUsers(props) {
|
||||
const params = LNbits.utils.prepareFilterQuery(this.usersTable, props)
|
||||
LNbits.api
|
||||
.request('GET', `/users/api/v1/user?${params}`)
|
||||
.then(res => {
|
||||
this.usersTable.loading = false
|
||||
this.usersTable.pagination.rowsNumber = res.data.total
|
||||
this.users = res.data.data
|
||||
this.updateChart(this.users)
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
fetchWallets(user_id) {
|
||||
LNbits.api
|
||||
.request('GET', `/users/api/v1/user/${user_id}/wallet`)
|
||||
.then(res => {
|
||||
this.wallets = res.data
|
||||
this.walletDialog.show = this.wallets.length > 0
|
||||
if (!this.walletDialog.show) {
|
||||
this.fetchUsers()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
toggleAdmin(user_id) {
|
||||
LNbits.api
|
||||
.request('GET', `/users/api/v1/user/${user_id}/admin`)
|
||||
.then(() => {
|
||||
this.fetchUsers()
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: 'Success! Toggled admin!',
|
||||
icon: null
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
},
|
||||
exportUsers() {
|
||||
console.log('export users')
|
||||
},
|
||||
topupCallback(res) {
|
||||
this.wallets.forEach(wallet => {
|
||||
if (res.wallet_id === wallet.id) {
|
||||
wallet.balance_msat += res.value * 1000
|
||||
}
|
||||
})
|
||||
this.fetchUsers()
|
||||
},
|
||||
topupWallet() {
|
||||
LNbits.api
|
||||
.request(
|
||||
'PUT',
|
||||
'/users/api/v1/topup',
|
||||
this.g.user.wallets[0].adminkey,
|
||||
this.wallet
|
||||
)
|
||||
.then(_ => {
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: `Success! Added ${this.wallet.amount} to ${this.wallet.id}`,
|
||||
icon: null
|
||||
})
|
||||
this.wallet = {}
|
||||
})
|
||||
.catch(function (error) {
|
||||
LNbits.utils.notifyApiError(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user