mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-25 23:21:21 +01:00
no more superuser url! delete cookie on logout add usr login feature fix node management * Cleaned up login form * CreateUser * information leak * cleaner parsing usr from url * rename decorators * login secret * fix: add back `superuser` command * chore: remove `fastapi_login` * fix: extract `token` from cookie * chore: prepare to extract user * feat: check user * chore: code clean-up * feat: happy flow working * fix: usr only login * fix: user already logged in * feat: check user in URL * fix: verify password at DB level * fix: do not show `Login` controls if user already logged in * fix: separate login endpoints * fix: remove `usr` param * chore: update error message * refactor: register method * feat: logout * chore: move comments * fix: remove user auth check from API * fix: user check unnecessary * fix: redirect after logout * chore: remove garbage files * refactor: simplify constructor call * fix: hide user icon if not authorized * refactor: rename auth env vars * chore: code clean-up * fix: add types for `python-jose` * fix: add types for `passlib` * fix: return type * feat: set default value for `auth_secret_key` to hash of super user * fix: default value * feat: rework login page * feat: ui polishing * feat: google auth * feat: add google auth * chore: remove `authlib` dependency * refactor: extract `_handle_sso_login` method * refactor: convert methods to `properties` * refactor: rename: `user_api` to `auth_api` * feat: store user info from SSO * chore: re-arange the buttons * feat: conditional rendering of login options * feat: correctly render buttons * fix: re-add `Claim Bitcoin` from the main page * fix: create wallet must send new user * fix: no `username-password` auth method * refactor: rename auth method * fix: do not force API level UUID4 validation * feat: add validation for username * feat: add account page * feat: update account * feat: add `has_password` for user * fix: email not editable * feat: validate email for existing account * fix: register check * feat: reset password * chore: code clean-up * feat: handle token expired * fix: only redirect if `text/html` * refactor: remove `OAuth2PasswordRequestForm` * chore: remove `python-multipart` dependency * fix: handle no headers for exception * feat: add back button on error screen * feat: show user profile image * fix: check account creation permissions * fix: auth for internal api call * chore: add some docs * chore: code clean-up * fix: rebase stuff * fix: default value types * refactor: customize error messages * fix: move types libs to dev dependencies * doc: specify the `Authorization callback URL` * fix: pass missing superuser id in node ui test * fix: keep usr param on wallet redirect removing usr param causes an issue if the browser doesnt yet have an access token. * fix: do not redirect if `wal` query param not present * fix: add nativeBuildInputs and buildInputs overrides to flake.nix * bump fastapi-sso to 0.9.0 which fixes some security issues * refactor: move the `lnbits_admin_extensions` to decorators * chore: bring package config from `dev` * chore: re-add dependencies * chore: re-add cev dependencies * chore: re-add mypy ignores * feat: i18n * refactor: move admin ext check to decorator (fix after rebase) * fix: label mapping * fix: re-fetch user after first wallet was created * fix: unlikely case that `user` is not found * refactor translations (move '*' to code) * reorganize deps in pyproject.toml, add comment * update flake.lock and simplify flake.nix after upstreaming overrides for fastapi-sso, types-passlib, types-pyasn1, types-python-jose were upstreamed in https://github.com/nix-community/poetry2nix/pull/1463 * fix: more relaxed email verification (by @prusnak) * fix: remove `\b` (boundaries) since we re using `fullmatch` * chore: `make bundle` --------- Co-authored-by: dni ⚡ <office@dnilabs.com> Co-authored-by: Arc <ben@arc.wales> Co-authored-by: jackstar12 <jkranawetter05@gmail.com> Co-authored-by: Pavol Rusnak <pavol@rusnak.io>
312 lines
8.9 KiB
JavaScript
312 lines
8.9 KiB
JavaScript
new Vue({
|
|
el: '#vue',
|
|
mixins: [windowMixin],
|
|
data: function () {
|
|
return {
|
|
settings: {},
|
|
logs: [],
|
|
serverlogEnabled: false,
|
|
lnbits_theme_options: [
|
|
'classic',
|
|
'bitcoin',
|
|
'flamingo',
|
|
'cyber',
|
|
'freedom',
|
|
'mint',
|
|
'autumn',
|
|
'monochrome',
|
|
'salvador'
|
|
],
|
|
auditData: {},
|
|
statusData: {},
|
|
statusDataTable: {
|
|
columns: [
|
|
{
|
|
name: 'date',
|
|
align: 'left',
|
|
label: this.$t('date'),
|
|
field: 'date'
|
|
},
|
|
{
|
|
name: 'message',
|
|
align: 'left',
|
|
label: this.$t('memo'),
|
|
field: 'message'
|
|
}
|
|
]
|
|
},
|
|
formData: {},
|
|
formAddAdmin: '',
|
|
formAddUser: '',
|
|
formAddExtensionsManifest: '',
|
|
formAllowedIPs: '',
|
|
formBlockedIPs: '',
|
|
isSuperUser: false,
|
|
wallet: {},
|
|
cancel: {},
|
|
topUpDialog: {
|
|
show: false
|
|
},
|
|
tab: 'funding',
|
|
needsRestart: false
|
|
}
|
|
},
|
|
created() {
|
|
this.getSettings()
|
|
this.getAudit()
|
|
this.balance = +'{{ balance|safe }}'
|
|
},
|
|
computed: {
|
|
lnbitsVersion() {
|
|
return LNBITS_VERSION
|
|
},
|
|
checkChanges() {
|
|
return !_.isEqual(this.settings, this.formData)
|
|
},
|
|
updateAvailable() {
|
|
return LNBITS_VERSION !== this.statusData.version
|
|
}
|
|
},
|
|
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
|
|
if (
|
|
addManifest &&
|
|
addManifest.length &&
|
|
!manifests.includes(addManifest)
|
|
) {
|
|
this.formData.lnbits_extensions_manifests = [...manifests, addManifest]
|
|
this.formAddExtensionsManifest = ''
|
|
}
|
|
},
|
|
removeExtensionsManifest(manifest) {
|
|
const manifests = this.formData.lnbits_extensions_manifests
|
|
this.formData.lnbits_extensions_manifests = manifests.filter(
|
|
m => m !== manifest
|
|
)
|
|
},
|
|
async toggleServerLog() {
|
|
this.serverlogEnabled = !this.serverlogEnabled
|
|
if (this.serverlogEnabled) {
|
|
const wsProto = location.protocol !== 'http:' ? 'wss://' : 'ws://'
|
|
const digestHex = await LNbits.utils.digestMessage(this.g.user.id)
|
|
const localUrl =
|
|
wsProto +
|
|
document.domain +
|
|
':' +
|
|
location.port +
|
|
'/api/v1/ws/' +
|
|
digestHex
|
|
this.ws = new WebSocket(localUrl)
|
|
this.ws.addEventListener('message', async ({data}) => {
|
|
this.logs.push(data.toString())
|
|
const scrollArea = this.$refs.logScroll
|
|
if (scrollArea) {
|
|
const scrollTarget = scrollArea.getScrollTarget()
|
|
const duration = 0
|
|
scrollArea.setScrollPosition(scrollTarget.scrollHeight, duration)
|
|
}
|
|
})
|
|
} else {
|
|
this.ws.close()
|
|
}
|
|
},
|
|
addAllowedIPs() {
|
|
const allowedIPs = this.formAllowedIPs.trim()
|
|
const allowed_ips = this.formData.lnbits_allowed_ips
|
|
if (
|
|
allowedIPs &&
|
|
allowedIPs.length &&
|
|
!allowed_ips.includes(allowedIPs)
|
|
) {
|
|
this.formData.lnbits_allowed_ips = [...allowed_ips, allowedIPs]
|
|
this.formAllowedIPs = ''
|
|
}
|
|
},
|
|
removeAllowedIPs(allowed_ip) {
|
|
const allowed_ips = this.formData.lnbits_allowed_ips
|
|
this.formData.lnbits_allowed_ips = allowed_ips.filter(
|
|
a => a !== allowed_ip
|
|
)
|
|
},
|
|
addBlockedIPs() {
|
|
const blockedIPs = this.formBlockedIPs.trim()
|
|
const blocked_ips = this.formData.lnbits_blocked_ips
|
|
if (
|
|
blockedIPs &&
|
|
blockedIPs.length &&
|
|
!blocked_ips.includes(blockedIPs)
|
|
) {
|
|
this.formData.lnbits_blocked_ips = [...blocked_ips, blockedIPs]
|
|
this.formBlockedIPs = ''
|
|
}
|
|
},
|
|
removeBlockedIPs(blocked_ip) {
|
|
const blocked_ips = this.formData.lnbits_blocked_ips
|
|
this.formData.lnbits_blocked_ips = blocked_ips.filter(
|
|
b => b !== blocked_ip
|
|
)
|
|
},
|
|
restartServer() {
|
|
LNbits.api
|
|
.request('GET', '/admin/api/v1/restart/')
|
|
.then(response => {
|
|
this.$q.notify({
|
|
type: 'positive',
|
|
message: 'Success! Restarted Server',
|
|
icon: null
|
|
})
|
|
this.needsRestart = false
|
|
})
|
|
.catch(function (error) {
|
|
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:
|
|
'Success! Added ' + this.wallet.amount + ' to ' + this.wallet.id,
|
|
icon: null
|
|
})
|
|
this.wallet = {}
|
|
})
|
|
.catch(function (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
},
|
|
formatDate(date) {
|
|
return moment(date * 1000).fromNow()
|
|
},
|
|
getNotifications() {
|
|
if (this.settings.lnbits_notifications) {
|
|
axios
|
|
.get(this.settings.lnbits_status_manifest)
|
|
.then(response => {
|
|
this.statusData = response.data
|
|
})
|
|
.catch(error => {
|
|
this.formData.lnbits_notifications = false
|
|
error.response.data = {}
|
|
error.response.data.message = 'Could not fetch status manifest.'
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
}
|
|
},
|
|
getAudit() {
|
|
LNbits.api
|
|
.request('GET', '/admin/api/v1/audit/', this.g.user.wallets[0].adminkey)
|
|
.then(response => {
|
|
this.auditData = response.data
|
|
})
|
|
.catch(function (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
},
|
|
getSettings() {
|
|
LNbits.api
|
|
.request(
|
|
'GET',
|
|
'/admin/api/v1/settings/',
|
|
this.g.user.wallets[0].adminkey
|
|
)
|
|
.then(response => {
|
|
this.isSuperUser = response.data.is_super_user || false
|
|
this.settings = response.data
|
|
this.formData = {...this.settings}
|
|
this.getNotifications()
|
|
})
|
|
.catch(function (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
},
|
|
updateSettings() {
|
|
let data = _.omit(this.formData, [
|
|
'is_super_user',
|
|
'lnbits_allowed_funding_sources'
|
|
])
|
|
LNbits.api
|
|
.request(
|
|
'PUT',
|
|
'/admin/api/v1/settings/',
|
|
this.g.user.wallets[0].adminkey,
|
|
data
|
|
)
|
|
.then(response => {
|
|
this.needsRestart =
|
|
this.settings.lnbits_backend_wallet_class !==
|
|
this.formData.lnbits_backend_wallet_class ||
|
|
this.settings.lnbits_killswitch !== this.formData.lnbits_killswitch
|
|
this.settings = this.formData
|
|
this.formData = _.clone(this.settings)
|
|
this.$q.notify({
|
|
type: 'positive',
|
|
message: `Success! Settings changed! ${
|
|
this.needsRestart ? 'Restart required!' : ''
|
|
}`,
|
|
icon: null
|
|
})
|
|
})
|
|
.catch(function (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
},
|
|
deleteSettings() {
|
|
LNbits.utils
|
|
.confirmDialog('Are you sure you want to restore settings to default?')
|
|
.onOk(() => {
|
|
LNbits.api
|
|
.request('DELETE', '/admin/api/v1/settings/')
|
|
.then(response => {
|
|
this.$q.notify({
|
|
type: 'positive',
|
|
message:
|
|
'Success! Restored settings to defaults, restart required!',
|
|
icon: null
|
|
})
|
|
this.needsRestart = true
|
|
})
|
|
.catch(function (error) {
|
|
LNbits.utils.notifyApiError(error)
|
|
})
|
|
})
|
|
},
|
|
downloadBackup() {
|
|
window.open('/admin/api/v1/backup/', '_blank')
|
|
}
|
|
}
|
|
})
|