fix: the username and picture (#3638)

Co-authored-by: dni  <office@dnilabs.com>
This commit is contained in:
Tiago Vasconcelos 2025-12-08 14:03:29 +00:00 committed by GitHub
parent b4c0cdbc7c
commit 7b635a31e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 60 additions and 74 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,6 +6,7 @@ window.LNbits = {
user(data) { user(data) {
const obj = { const obj = {
id: data.id, id: data.id,
username: data.username,
admin: data.admin, admin: data.admin,
email: data.email, email: data.email,
extensions: data.extensions, extensions: data.extensions,

View file

@ -38,12 +38,6 @@ window.app.component('lnbits-header', {
customLogoUrl() { customLogoUrl() {
return this.USE_CUSTOM_LOGO || null return this.USE_CUSTOM_LOGO || null
}, },
userPictureUrl() {
return this.g.user.extra.picture
},
hasUserPicture() {
return this.g.user && this.g.user.extra && this.g.user.extra.picture != ''
},
showAdmin() { showAdmin() {
return this.g.user && (this.g.user.super_user || this.g.user.admin) return this.g.user && (this.g.user.super_user || this.g.user.admin)
}, },
@ -53,6 +47,7 @@ window.app.component('lnbits-header', {
displayName() { displayName() {
return ( return (
this.g.user?.extra?.display_name || this.g.user?.extra?.display_name ||
this.g.user.username ||
this.g.user?.extra?.first_name || this.g.user?.extra?.first_name ||
'Anon' 'Anon'
) )

View file

@ -3,7 +3,6 @@ window.PageAccount = {
mixins: [window.windowMixin], mixins: [window.windowMixin],
data() { data() {
return { return {
user: null,
untouchedUser: null, untouchedUser: null,
hasUsername: false, hasUsername: false,
showUserId: false, showUserId: false,
@ -211,7 +210,7 @@ window.PageAccount = {
}, },
computed: { computed: {
isUserTouched() { isUserTouched() {
return JSON.stringify(this.user) !== JSON.stringify(this.untouchedUser) return !_.isEqual(this.g.user, this.untouchedUser)
} }
}, },
methods: { methods: {
@ -229,14 +228,13 @@ window.PageAccount = {
'/api/v1/auth/update', '/api/v1/auth/update',
null, null,
{ {
user_id: this.user.id, user_id: this.g.user.id,
username: this.user.username, username: this.g.user.username,
email: this.user.email, email: this.g.user.email,
extra: this.user.extra extra: this.g.user.extra
} }
) )
this.user = data this.untouchedUser = JSON.parse(JSON.stringify(this.g.user))
this.untouchedUser = JSON.parse(JSON.stringify(data))
this.hasUsername = !!data.username this.hasUsername = !!data.username
Quasar.Notify.create({ Quasar.Notify.create({
type: 'positive', type: 'positive',
@ -268,14 +266,13 @@ window.PageAccount = {
'/api/v1/auth/password', '/api/v1/auth/password',
null, null,
{ {
user_id: this.user.id, user_id: this.g.user.id,
username: this.credentialsData.username, username: this.credentialsData.username,
password_old: this.credentialsData.oldPassword, password_old: this.credentialsData.oldPassword,
password: this.credentialsData.newPassword, password: this.credentialsData.newPassword,
password_repeat: this.credentialsData.newPasswordRepeat password_repeat: this.credentialsData.newPasswordRepeat
} }
) )
this.user = data
this.untouchedUser = JSON.parse(JSON.stringify(data)) this.untouchedUser = JSON.parse(JSON.stringify(data))
this.hasUsername = !!data.username this.hasUsername = !!data.username
this.credentialsData.show = false this.credentialsData.show = false
@ -294,11 +291,10 @@ window.PageAccount = {
'/api/v1/auth/pubkey', '/api/v1/auth/pubkey',
null, null,
{ {
user_id: this.user.id, user_id: this.g.user.id,
pubkey: this.credentialsData.pubkey pubkey: this.credentialsData.pubkey
} }
) )
this.user = data
this.untouchedUser = JSON.parse(JSON.stringify(data)) this.untouchedUser = JSON.parse(JSON.stringify(data))
this.hasUsername = !!data.username this.hasUsername = !!data.username
this.credentialsData.show = false this.credentialsData.show = false
@ -314,8 +310,8 @@ window.PageAccount = {
this.credentialsData = { this.credentialsData = {
show: true, show: true,
oldPassword: null, oldPassword: null,
username: this.user.username, username: this.g.user.username,
pubkey: this.user.pubkey, pubkey: this.g.user.pubkey,
newPassword: null, newPassword: null,
newPasswordRepeat: null newPasswordRepeat: null
} }
@ -431,7 +427,7 @@ window.PageAccount = {
'/api/v1/auth/acl', '/api/v1/auth/acl',
null, null,
{ {
id: this.user.id, id: this.g.user.id,
password: this.apiAcl.password, password: this.apiAcl.password,
...this.selectedApiAcl ...this.selectedApiAcl
} }
@ -632,8 +628,8 @@ window.PageAccount = {
}) })
return return
} }
this.user.extra.labels = this.user.extra.labels || [] this.g.user.extra.labels = this.g.user.extra.labels || []
const duplicate = this.user.extra.labels.find( const duplicate = this.g.user.extra.labels.find(
label => label.name === this.labelsDialog.data.name label => label.name === this.labelsDialog.data.name
) )
if (duplicate) { if (duplicate) {
@ -643,7 +639,7 @@ window.PageAccount = {
}) })
return return
} }
this.user.extra.labels.unshift({...this.labelsDialog.data}) this.g.user.extra.labels.unshift({...this.labelsDialog.data})
this.labelsDialog.show = false this.labelsDialog.show = false
return true return true
}, },
@ -665,13 +661,15 @@ window.PageAccount = {
}, },
updateUserLabel() { updateUserLabel() {
const label = this.labelsDialog.data const label = this.labelsDialog.data
const existingLabels = JSON.parse(JSON.stringify(this.user.extra.labels)) const existingLabels = JSON.parse(
this.user.extra.labels = this.user.extra.labels.filter( JSON.stringify(this.g.user.extra.labels)
)
this.g.user.extra.labels = this.g.user.extra.labels.filter(
l => l.name !== label.name l => l.name !== label.name
) )
const labelUpdated = this.addUserLabel() const labelUpdated = this.addUserLabel()
if (!labelUpdated) { if (!labelUpdated) {
this.user.extra.labels = existingLabels this.g.user.extra.labels = existingLabels
} }
this.labelsDialog.show = false this.labelsDialog.show = false
}, },
@ -679,7 +677,7 @@ window.PageAccount = {
LNbits.utils LNbits.utils
.confirmDialog('Are you sure you want to delete this label?') .confirmDialog('Are you sure you want to delete this label?')
.onOk(() => { .onOk(() => {
this.user.extra.labels = this.user.extra.labels.filter( this.g.user.extra.labels = this.g.user.extra.labels.filter(
l => l.name !== label.name l => l.name !== label.name
) )
}) })
@ -687,21 +685,13 @@ window.PageAccount = {
}, },
async created() { async created() {
try { this.untouchedUser = JSON.parse(JSON.stringify(this.g.user))
const {data} = await LNbits.api.getAuthenticatedUser() this.hasUsername = !!this.g.user.username
this.user = data
this.untouchedUser = JSON.parse(JSON.stringify(data))
this.hasUsername = !!data.username
if (!this.user.extra) this.user.extra = {}
} catch (e) {
LNbits.utils.notifyApiError(e)
}
if (this.$route.hash.length > 1) { if (this.$route.hash.length > 1) {
this.tab = this.$route.hash.replace('#', '') this.tab = this.$route.hash.replace('#', '')
} }
await this.getApiACLs() await this.getApiACLs()
await this.getUserAssets() await this.getUserAssets()
// filter out themes that are not allowed // filter out themes that are not allowed
this.themeOptions = this.themeOptions.filter(theme => this.themeOptions = this.themeOptions.filter(theme =>
this.LNBITS_THEME_OPTIONS.includes(theme.name) this.LNBITS_THEME_OPTIONS.includes(theme.name)

View file

@ -81,16 +81,16 @@
class="q-pl-sm" class="q-pl-sm"
> >
<template v-slot:label> <template v-slot:label>
<q-avatar v-if="hasUserPicture" size="18px"> <q-avatar v-if="g.user?.extra?.picture !== ''" size="18px">
<q-img :src="userPictureUrl"></q-img> <q-img :src="g.user?.extra?.picture"></q-img>
</q-avatar> </q-avatar>
<q-avatar v-else icon="account_circle"></q-avatar> <q-avatar v-else icon="account_circle" size="18px"></q-avatar>
</template> </template>
<q-list style="max-width: 200px"> <q-list style="max-width: 200px">
<q-item> <q-item>
<q-item-section avatar v-if="hasUserPicture"> <q-item-section avatar v-if="g.user?.extra?.picture !== ''">
<q-avatar size="md"> <q-avatar size="md">
<img :src="userPictureUrl" /> <img :src="g.user?.extra?.picture" />
</q-avatar> </q-avatar>
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>

View file

@ -90,7 +90,7 @@
</template> </template>
<template v-slot:after> <template v-slot:after>
<q-scroll-area style="height: 80vh"> <q-scroll-area style="height: 80vh">
<q-tab-panels v-if="user" v-model="tab"> <q-tab-panels v-if="g.user" v-model="tab">
<q-tab-panel name="user"> <q-tab-panel name="user">
<div v-if="credentialsData.show"> <div v-if="credentialsData.show">
<q-card-section> <q-card-section>
@ -102,9 +102,9 @@
</div> </div>
<div class="col"> <div class="col">
<q-img <q-img
v-if="user.extra.picture" v-if="g.user.extra.picture"
style="max-width: 100px" style="max-width: 100px"
:src="user.extra.picture" :src="g.user.extra.picture"
class="float-right" class="float-right"
></q-img> ></q-img>
</div> </div>
@ -120,7 +120,7 @@
class="q-mb-md" class="q-mb-md"
></q-input> ></q-input>
<q-input <q-input
v-if="user.has_password" v-if="g.user.has_password"
v-model="credentialsData.oldPassword" v-model="credentialsData.oldPassword"
type="password" type="password"
autocomplete="off" autocomplete="off"
@ -202,12 +202,12 @@
</q-card-section> </q-card-section>
</div> </div>
<div v-else> <div v-else>
<q-card-section v-if="user.extra.picture"> <q-card-section v-if="g.user.extra.picture">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<q-img <q-img
style="max-width: 100px" style="max-width: 100px"
:src="user.extra.picture" :src="g.user.extra.picture"
class="float-right" class="float-right"
></q-img> ></q-img>
</div> </div>
@ -216,7 +216,7 @@
<q-card-section> <q-card-section>
<q-input <q-input
v-model="user.id" v-model="g.user.id"
:label="$t('user_id')" :label="$t('user_id')"
filled filled
dense dense
@ -232,7 +232,7 @@
></q-btn> ></q-btn>
</q-input> </q-input>
<q-input <q-input
v-model="user.username" v-model="g.user.username"
:label="$t('username')" :label="$t('username')"
filled filled
dense dense
@ -241,7 +241,7 @@
> >
</q-input> </q-input>
<q-input <q-input
v-model="user.pubkey" v-model="g.user.pubkey"
:label="$t('pubkey')" :label="$t('pubkey')"
filled filled
dense dense
@ -250,7 +250,7 @@
> >
</q-input> </q-input>
<q-input <q-input
v-model="user.email" v-model="g.user.email"
:label="$t('email')" :label="$t('email')"
filled filled
dense dense
@ -258,8 +258,8 @@
class="q-mb-md" class="q-mb-md"
> >
</q-input> </q-input>
<div v-if="!user.email" class="row"></div> <div v-if="!g.user.email" class="row"></div>
<div v-if="!user.email" class="row"> <div v-if="!g.user.email" class="row">
{% if "google-auth" in LNBITS_AUTH_METHODS or {% if "google-auth" in LNBITS_AUTH_METHODS or
"github-auth" in LNBITS_AUTH_METHODS %} "github-auth" in LNBITS_AUTH_METHODS %}
<div class="col q-pa-sm text-h6"> <div class="col q-pa-sm text-h6">
@ -268,7 +268,7 @@
{%endif%} {% if "google-auth" in LNBITS_AUTH_METHODS %} {%endif%} {% if "google-auth" in LNBITS_AUTH_METHODS %}
<div class="col q-pa-sm"> <div class="col q-pa-sm">
<q-btn <q-btn
:href="`/api/v1/auth/google?user_id=${user.id}`" :href="`/api/v1/auth/google?user_id=${g.user.id}`"
type="a" type="a"
outline outline
no-caps no-caps
@ -287,7 +287,7 @@
{%endif%} {% if "github-auth" in LNBITS_AUTH_METHODS %} {%endif%} {% if "github-auth" in LNBITS_AUTH_METHODS %}
<div class="col q-pa-sm"> <div class="col q-pa-sm">
<q-btn <q-btn
:href="`/api/v1/auth/github?user_id=${user.id}`" :href="`/api/v1/auth/github?user_id=${g.user.id}`"
type="a" type="a"
outline outline
no-caps no-caps
@ -307,9 +307,9 @@
</div> </div>
</q-card-section> </q-card-section>
<q-card-section v-if="user.extra"> <q-card-section v-if="g.user.extra">
<q-input <q-input
v-model="user.extra.first_name" v-model="g.user.extra.first_name"
:label="$t('first_name')" :label="$t('first_name')"
filled filled
dense dense
@ -317,7 +317,7 @@
> >
</q-input> </q-input>
<q-input <q-input
v-model="user.extra.last_name" v-model="g.user.extra.last_name"
:label="$t('last_name')" :label="$t('last_name')"
filled filled
dense dense
@ -325,7 +325,7 @@
> >
</q-input> </q-input>
<q-input <q-input
v-model="user.extra.provider" v-model="g.user.extra.provider"
:label="$t('auth_provider')" :label="$t('auth_provider')"
filled filled
dense dense
@ -334,7 +334,7 @@
> >
</q-input> </q-input>
<q-input <q-input
v-model="user.external_id" v-model="g.user.external_id"
:label="$t('external_id')" :label="$t('external_id')"
filled filled
dense dense
@ -344,7 +344,7 @@
</q-input> </q-input>
<q-input <q-input
v-model="user.extra.picture" v-model="g.user.extra.picture"
:label="$t('picture')" :label="$t('picture')"
:hint="$t('user_picture_desc')" :hint="$t('user_picture_desc')"
filled filled
@ -389,7 +389,7 @@
</div> </div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-model="user.extra.visible_wallet_count" v-model="g.user.extra.visible_wallet_count"
:label="$t('visible_wallet_count')" :label="$t('visible_wallet_count')"
filled filled
dense dense
@ -533,7 +533,7 @@
<q-input <q-input
filled filled
dense dense
v-model="user.extra.notifications.nostr_identifier" v-model="g.user.extra.notifications.nostr_identifier"
:hint="$t('notifications_nostr_identifier_desc')" :hint="$t('notifications_nostr_identifier_desc')"
> >
</q-input> </q-input>
@ -553,7 +553,7 @@
<q-input <q-input
filled filled
dense dense
v-model="user.extra.notifications.telegram_chat_id" v-model="g.user.extra.notifications.telegram_chat_id"
:hint="$t('notifications_chat_id_desc')" :hint="$t('notifications_chat_id_desc')"
/> />
</div> </div>
@ -573,7 +573,7 @@
min="0" min="0"
step="1" step="1"
v-model=" v-model="
user.extra.notifications.outgoing_payments_sats g.user.extra.notifications.outgoing_payments_sats
" "
:hint="$t('notification_outgoing_payment_desc')" :hint="$t('notification_outgoing_payment_desc')"
/> />
@ -593,7 +593,7 @@
min="0" min="0"
step="1" step="1"
v-model=" v-model="
user.extra.notifications.incoming_payments_sats g.user.extra.notifications.incoming_payments_sats
" "
:hint="$t('notification_incoming_payment_desc')" :hint="$t('notification_incoming_payment_desc')"
/> />
@ -610,7 +610,7 @@
emit-value emit-value
map-options map-options
multiple multiple
v-model="user.extra.notifications.excluded_wallets" v-model="g.user.extra.notifications.excluded_wallets"
:options="g.user.walletOptions" :options="g.user.walletOptions"
:label="$t('exclude_wallets')" :label="$t('exclude_wallets')"
:hint="$t('notifications_excluded_wallets_desc')" :hint="$t('notifications_excluded_wallets_desc')"
@ -623,7 +623,7 @@
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="api_acls"> <q-tab-panel name="api_acls">
<div class="row q-mb-md"> <div class="row q-mb-md">
<q-badge v-if="user.admin"> <q-badge v-if="g.user.admin">
<span <span
v-text="$t('access_control_list_admin_warning')" v-text="$t('access_control_list_admin_warning')"
></span> ></span>
@ -1081,7 +1081,7 @@
<q-separator></q-separator> <q-separator></q-separator>
<q-card-section> <q-card-section>
<q-table <q-table
:rows="user.extra.labels" :rows="g.user.extra.labels"
:columns="labelsTable.columns" :columns="labelsTable.columns"
v-model:pagination="labelsTable.pagination" v-model:pagination="labelsTable.pagination"
:loading="labelsTable.loading" :loading="labelsTable.loading"
@ -1327,7 +1327,7 @@
></q-btn> ></q-btn>
<q-btn <q-btn
v-if=" v-if="
user.extra.labels.some( g.user.extra.labels.some(
label => label.name === labelsDialog.data.name label => label.name === labelsDialog.data.name
) )
" "