feat: send invitation code to backend
This commit is contained in:
@@ -318,6 +318,7 @@ class RegisterUser(BaseModel):
|
||||
username: str = Query(default=..., min_length=2, max_length=20)
|
||||
password: str = Query(default=..., min_length=8, max_length=50)
|
||||
password_repeat: str = Query(default=..., min_length=8, max_length=50)
|
||||
invitation_code: str | None = Query(default=None, min_length=1, max_length=256)
|
||||
|
||||
|
||||
class CreateUser(BaseModel):
|
||||
|
||||
@@ -366,6 +366,9 @@ async def register(data: RegisterUser) -> JSONResponse:
|
||||
if data.email and not is_valid_email_address(data.email):
|
||||
raise HTTPException(HTTPStatus.BAD_REQUEST, "Invalid email.")
|
||||
|
||||
if not await check_register_activation_settings(data):
|
||||
raise HTTPException(HTTPStatus.FORBIDDEN, "User activation failed.")
|
||||
|
||||
account = Account(
|
||||
id=uuid4().hex,
|
||||
email=data.email,
|
||||
@@ -376,6 +379,21 @@ async def register(data: RegisterUser) -> JSONResponse:
|
||||
return _auth_success_response(account.username, account.id, account.email)
|
||||
|
||||
|
||||
async def check_register_activation_settings(data: RegisterUser) -> bool:
|
||||
if not settings.lnbits_require_user_activation:
|
||||
return True
|
||||
if settings.lnbits_user_activation_by_invitation_code and data.invitation_code:
|
||||
code = data.invitation_code.strip()
|
||||
if code == settings.lnbits_register_reusable_activation_code:
|
||||
return True
|
||||
if code in settings.lnbits_register_one_time_activation_codes:
|
||||
settings.lnbits_register_one_time_activation_codes.remove(code)
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@auth_router.put("/pubkey")
|
||||
async def update_pubkey(
|
||||
data: UpdateUserPubkey,
|
||||
|
||||
@@ -1197,6 +1197,12 @@ class PublicSettings(BaseModel):
|
||||
wallet_featured_button_label: str | None = Field(alias="walletFeaturedButtonLabel")
|
||||
wallet_featured_button_url: str | None = Field(alias="walletFeaturedButtonUrl")
|
||||
wallet_featured_button_icon: str | None = Field(alias="walletFeaturedButtonIcon")
|
||||
lnbits_user_activation_by_email: bool = Field(alias="userActivationByEmail")
|
||||
lnbits_user_activation_by_nostr: bool = Field(alias="userActivationByNostr")
|
||||
lnbits_user_activation_by_payment: bool = Field(alias="userActivationByPayment")
|
||||
lnbits_user_activation_by_invitation_code: bool = Field(
|
||||
alias="userActivationByInvitationCode"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_settings(cls, settings: Settings):
|
||||
@@ -1248,6 +1254,10 @@ class PublicSettings(BaseModel):
|
||||
walletFeaturedButtonLabel=settings.lnbits_wallet_featured_button_label,
|
||||
walletFeaturedButtonUrl=settings.lnbits_wallet_featured_button_url,
|
||||
walletFeaturedButtonIcon=settings.lnbits_wallet_featured_button_icon,
|
||||
userActivationByEmail=settings.lnbits_user_activation_by_email,
|
||||
userActivationByNostr=settings.lnbits_user_activation_by_nostr,
|
||||
userActivationByPayment=settings.lnbits_user_activation_by_payment,
|
||||
userActivationByInvitationCode=settings.lnbits_user_activation_by_invitation_code,
|
||||
)
|
||||
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -285,7 +285,7 @@ window.localisation.en = {
|
||||
'Nip5 identifier to send notifications to',
|
||||
notifications_nostr_identifiers: 'Nostr Identifiers',
|
||||
notifications_nostr_identifiers_desc:
|
||||
'List of identifiers to send notifications to',
|
||||
'List of identifiers to send notifications to.',
|
||||
|
||||
notifications_telegram_config: 'Telegram Configuration',
|
||||
notifications_enable_telegram: 'Enable Telegram',
|
||||
@@ -724,6 +724,9 @@ window.localisation.en = {
|
||||
confirmation_code_hint: 'The confirmation code that you have received.',
|
||||
email: 'Email',
|
||||
email_confirmation_hint: 'Email address to send the confirmation code to.',
|
||||
nostr_identifier: 'Nostr Identifier',
|
||||
nostr_identifier_hint:
|
||||
'Nostr nip5 identifier or <npub> to send the confirmation code to.',
|
||||
|
||||
new_user_not_allowed: 'Registration is disabled.',
|
||||
start_user_impersonation: 'Impersonate this user',
|
||||
|
||||
@@ -434,6 +434,7 @@ window.app.component('username-password', {
|
||||
password_2: String,
|
||||
resetKey: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
oauth: [
|
||||
@@ -449,7 +450,8 @@ window.app.component('username-password', {
|
||||
confirmationMethod: 'code',
|
||||
confirmationEmail: '',
|
||||
confirmationCode: '',
|
||||
showConfirmationCode: false
|
||||
showConfirmationCode: false,
|
||||
nostrConfirmationIdentifier: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -553,6 +555,33 @@ window.app.component('username-password', {
|
||||
computed: {
|
||||
showOauth() {
|
||||
return this.oauth.some(m => this.authMethods.includes(m))
|
||||
},
|
||||
disableRegister() {
|
||||
const usernameOK = !!this.username
|
||||
const passwordOK = !!this.password && this.password.length >= 8
|
||||
const passwordsMatch = this.password === this.passwordRepeat
|
||||
const codeOk =
|
||||
this.confirmationMethodsCount === 0 ||
|
||||
this.confirmationMethod !== 'code' ||
|
||||
this.confirmationCode.length > 0
|
||||
|
||||
const nostrOk =
|
||||
this.confirmationMethodsCount === 0 ||
|
||||
this.confirmationMethod !== 'nostr' ||
|
||||
this.nostrConfirmationIdentifier.length > 0
|
||||
|
||||
return (
|
||||
!usernameOK || !passwordOK || !passwordsMatch || !codeOk || !nostrOk
|
||||
)
|
||||
},
|
||||
confirmationMethodsCount() {
|
||||
const methods = [
|
||||
this.g.settings.userActivationByEmail,
|
||||
this.g.settings.userActivationByNostr,
|
||||
this.g.settings.userActivationByPayment,
|
||||
this.g.settings.userActivationByInvitationCode
|
||||
]
|
||||
return methods.filter(Boolean).length
|
||||
}
|
||||
},
|
||||
created() {}
|
||||
|
||||
@@ -814,20 +814,54 @@ include('components/lnbits-error.vue') %}
|
||||
type="password"
|
||||
:rules="[val => !val || val.length >= 8 || $t('invalid_password')]"
|
||||
></q-input>
|
||||
<div class="row justify-center q-mb-md">
|
||||
<div
|
||||
v-if="confirmationMethodsCount > 0"
|
||||
class="q-my-md q-pa-sm text-body2 text-grey-4 bg-grey-9 rounded-borders"
|
||||
>
|
||||
<q-icon name="info" color="orange-4" class="q-mr-xs"></q-icon>
|
||||
|
||||
Confirmation required before you can log in.
|
||||
<div v-if="confirmationMethodsCount > 1">
|
||||
Please choose one of the methods below.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="confirmationMethodsCount > 1"
|
||||
class="row justify-center q-mb-md"
|
||||
>
|
||||
<q-tabs
|
||||
v-model="confirmationMethod"
|
||||
dense
|
||||
active-color="primary"
|
||||
indicator-color="primary"
|
||||
>
|
||||
<q-tab name="code" icon="confirmation_number" label="Code"></q-tab>
|
||||
<q-tab name="payment" icon="bolt" label="Payment"></q-tab>
|
||||
<q-tab name="nostr" icon="bolt" label="Nostr"></q-tab>
|
||||
<q-tab name="email" icon="email" label="Email"></q-tab>
|
||||
<q-tab
|
||||
v-if="g.settings.userActivationByInvitationCode"
|
||||
name="code"
|
||||
icon="confirmation_number"
|
||||
label="Code"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
v-if="g.settings.userActivationByPayment"
|
||||
name="payment"
|
||||
icon="bolt"
|
||||
label="Payment"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
v-if="g.settings.userActivationByNostr"
|
||||
name="nostr"
|
||||
icon="bolt"
|
||||
label="Nostr"
|
||||
></q-tab>
|
||||
<q-tab
|
||||
v-if="g.settings.userActivationByEmail"
|
||||
name="email"
|
||||
icon="email"
|
||||
label="Email"
|
||||
></q-tab>
|
||||
</q-tabs>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="confirmationMethodsCount > 0" class="q-mb-md">
|
||||
<q-tab-panels v-model="confirmationMethod">
|
||||
<q-tab-panel name="code" class="q-pa-none">
|
||||
<div>
|
||||
@@ -854,8 +888,17 @@ include('components/lnbits-error.vue') %}
|
||||
<q-tab-panel name="payment">
|
||||
<div>payment</div>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="nostr">
|
||||
<div>nostr</div>
|
||||
<q-tab-panel name="nostr" class="q-pa-none">
|
||||
<div>
|
||||
<q-input
|
||||
dense
|
||||
filled
|
||||
v-model="nostrConfirmationIdentifier"
|
||||
:label="$t('nostr_identifier')"
|
||||
:hint="$t('nostr_identifier_hint')"
|
||||
>
|
||||
</q-input>
|
||||
</div>
|
||||
</q-tab-panel>
|
||||
<q-tab-panel name="email" class="q-pa-none">
|
||||
<div>
|
||||
@@ -876,12 +919,7 @@ include('components/lnbits-error.vue') %}
|
||||
<q-btn
|
||||
unelevated
|
||||
color="primary"
|
||||
:disable="
|
||||
!password ||
|
||||
!passwordRepeat ||
|
||||
!username ||
|
||||
password !== passwordRepeat
|
||||
"
|
||||
:disable="disableRegister"
|
||||
type="submit"
|
||||
class="full-width"
|
||||
:label="$t('create_account')"
|
||||
|
||||
@@ -281,7 +281,6 @@
|
||||
<div class="row items-center">
|
||||
<q-toggle
|
||||
size="md"
|
||||
disable
|
||||
:label="
|
||||
formData.lnbits_user_activation_by_nostr
|
||||
? $t('enabled')
|
||||
|
||||
Reference in New Issue
Block a user