Prompt for private key if needed

This commit is contained in:
styppo 2023-01-20 18:47:53 +00:00
parent 856043bae2
commit 1b5033f3d9
No known key found for this signature in database
GPG Key ID: 3AAA685C50724C28
4 changed files with 43 additions and 24 deletions

View File

@ -1,5 +1,5 @@
<template> <template>
<q-dialog v-model="app.signInDialog.open" @before-show="updateFragment" @hide="onClose"> <q-dialog v-model="app.signInDialog.open" @before-show="updateFragment" @hide="onClose" ref="signInDialog">
<div class="sign-in-dialog"> <div class="sign-in-dialog">
<q-btn <q-btn
v-if="showClose" v-if="showClose"
@ -39,14 +39,7 @@
<SignUpForm v-if="fragment === 'sign-up'" @complete="onComplete" /> <SignUpForm v-if="fragment === 'sign-up'" @complete="onComplete" />
<SignInForm v-if="fragment === 'sign-in'" @complete="onComplete"/> <SignInForm v-if="fragment === 'sign-in'" @complete="onComplete"/>
<SignInForm v-if="fragment === 'private-key'" @complete="onComplete" private-key-only />
<div v-if="fragment === 'complete'" class="complete">
<h3>Signed in as</h3>
<p>
<UserName v-if="pubkey" :pubkey="pubkey" two-line />
</p>
<button class="btn btn-primary" v-close-popup>Let's go</button>
</div>
</div> </div>
</q-dialog> </q-dialog>
</template> </template>
@ -54,7 +47,6 @@
<script> <script>
import Logo from 'components/Logo.vue' import Logo from 'components/Logo.vue'
import UserAvatar from 'components/User/UserAvatar.vue' import UserAvatar from 'components/User/UserAvatar.vue'
import UserName from 'components/User/UserName.vue'
import SignUpForm from 'components/SignIn/SignUpForm.vue' import SignUpForm from 'components/SignIn/SignUpForm.vue'
import SignInForm from 'components/SignIn/SignInForm.vue' import SignInForm from 'components/SignIn/SignInForm.vue'
import {useAppStore} from 'stores/App' import {useAppStore} from 'stores/App'
@ -64,7 +56,6 @@ import Nip07 from 'src/utils/Nip07'
export default { export default {
name: 'SignInDialog', name: 'SignInDialog',
components: { components: {
UserName,
Logo, Logo,
UserAvatar, UserAvatar,
SignInForm, SignInForm,
@ -91,11 +82,10 @@ export default {
}, },
computed: { computed: {
showClose() { showClose() {
return this.fragment === 'welcome' return this.fragment === 'welcome' || !this.backAllowed
|| (this.fragment !== 'complete' && !this.backAllowed)
}, },
showBack() { showBack() {
return this.fragment !== 'complete' && !this.showClose return !this.showClose
}, },
nip07available() { nip07available() {
return Nip07.isAvailable() return Nip07.isAvailable()
@ -111,7 +101,7 @@ export default {
}, },
onComplete({pubkey}) { onComplete({pubkey}) {
this.pubkey = pubkey this.pubkey = pubkey
this.fragment = 'complete' this.$refs.signInDialog.hide()
}, },
updateFragment() { updateFragment() {
this.fragment = this.app.signInDialog.fragment || 'welcome' this.fragment = this.app.signInDialog.fragment || 'welcome'

View File

@ -1,20 +1,19 @@
<template> <template>
<div class="sign-in"> <div class="sign-in">
<h3>Log in</h3> <h3>{{ header }}</h3>
<q-form @submit.stop="signIn"> <q-form @submit.stop="signIn">
<label for="private-key">Paste your public or private key</label> <label for="private-key">{{ prompt }}</label>
<input <input
ref="input" ref="input"
v-model="key" v-model="key"
id="private-key" :placeholder="placeholder"
placeholder="npub… / nsec…"
maxlength="63" maxlength="63"
:class="{ :class="{
valid: validKey, valid: validKey,
invalid: invalidKey, invalid: invalidKey,
}" }"
/> />
<button type="submit" class="btn btn-primary" :disabled="!validKey">Log in</button> <button type="submit" class="btn btn-primary" :disabled="!validKey">{{ buttonLabel }}</button>
</q-form> </q-form>
</div> </div>
</template> </template>
@ -27,12 +26,42 @@ import {useSettingsStore} from 'stores/Settings'
export default { export default {
name: 'SignInForm', name: 'SignInForm',
emits: ['complete'], emits: ['complete'],
props: {
privateKeyOnly: {
type: Boolean,
default: false,
}
},
data() { data() {
return { return {
key: null, key: null,
} }
}, },
computed: { computed: {
header() {
// TODO i18n
return this.privateKeyOnly
? 'Private key needed'
: 'Log in'
},
prompt() {
// TODO i18n
return this.privateKeyOnly
? 'Paste your private key to continue'
: 'Paste your public or private key'
},
placeholder() {
// TODO i18n
return this.privateKeyOnly
? 'nsec…'
: 'npub… / nsec…'
},
buttonLabel() {
// TODO i18n
return this.privateKeyOnly
? 'Continue'
: 'Log in'
},
validKey() { validKey() {
return this.isValidKey(this.key) return this.isValidKey(this.key)
}, },
@ -47,7 +76,7 @@ export default {
if (!str) return false if (!str) return false
try { try {
const {data, prefix} = bech32decode(str.toLowerCase()) const {data, prefix} = bech32decode(str.toLowerCase())
return data.byteLength === 32 && prefix === 'npub' || prefix === 'nsec' return data.byteLength === 32 && ((prefix === 'npub' && !this.privateKeyOnly) || prefix === 'nsec')
} catch (e) { } catch (e) {
return false return false
} }

View File

@ -26,7 +26,6 @@ export class Account {
let {sig} = await Nip07.signEvent(event) let {sig} = await Nip07.signEvent(event)
event.sig = sig event.sig = sig
} else { } else {
// TODO
throw new Error('cannot sign') throw new Error('cannot sign')
} }
return event return event

View File

@ -42,8 +42,9 @@ export const useAppStore = defineStore('app', {
this.createPostDialog.params = options this.createPostDialog.params = options
this.createPostDialog.open = true this.createPostDialog.open = true
}, },
signEvent(event) { async signEvent(event) {
// TODO Check if signing is possible, prompt for privkey if (!await this.signInIfNeeded()) return
if (!this.activeAccount.canSign() && !await this.signIn('private-key')) return
return this.activeAccount.sign(event) return this.activeAccount.sign(event)
} }
}, },