release: v1.0.4
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s

Add PasswordInput with show/hide toggle, align legacy setup/register
routing, merge duplicate i18n keys, and remove unused jose dependency.
This commit is contained in:
O96u committed 2026-08-25 16:11:50 +08:00
1 parent 661146ce20
commit 7c45a78572
13 files changed
+107 -70

No files matched your search

+2 -15
View File
@@ -2,10 +2,6 @@
import logoLight from '~/assets/image/logo-light.png'
import logoDark from '~/assets/image/logo-dark.png'
const emit = defineEmits<{
success: []
}>()
const router = useRouter()
const { login, fetchStatus, authStatus } = useAuth()
const toast = useToast()
@@ -47,7 +43,6 @@ async function submit() {
username.value = ''
password.value = ''
secret.value = ''
emit('success')
toast.add({ title: t('auth.loginSuccess'), color: 'success' })
} else {
toast.add({
@@ -108,15 +103,11 @@ async function submit() {
>
{{ t('auth.adminSecret') }}
</label>
<UInput
<PasswordInput
id="admin-secret"
v-model="secret"
type="password"
:placeholder="t('auth.adminSecretPlaceholder')"
autocomplete="current-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
@keyup.enter="submit"
/>
<p class="text-xs leading-relaxed text-muted">
@@ -151,15 +142,11 @@ async function submit() {
>
{{ t('auth.password') }}
</label>
<UInput
<PasswordInput
id="login-password"
v-model="password"
type="password"
:placeholder="t('auth.password')"
autocomplete="current-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
@keyup.enter="submit"
/>
</div>
+50
View File
@@ -0,0 +1,50 @@
<script setup lang="ts">
defineOptions({
inheritAttrs: false
})
const model = defineModel<string>({ default: '' })
defineProps<{
id?: string
placeholder?: string
autocomplete?: string
}>()
const show = ref(false)
const { t } = useI18n()
</script>
<template>
<UInput
:id="id"
v-model="model"
:type="show ? 'text' : 'password'"
:placeholder="placeholder"
:autocomplete="autocomplete"
size="lg"
class="w-full"
:ui="{ root: 'w-full', trailing: 'pe-1' }"
v-bind="$attrs"
>
<template #trailing>
<UButton
color="neutral"
variant="link"
size="sm"
:icon="show ? 'i-lucide-eye-off' : 'i-lucide-eye'"
:aria-label="show ? t('auth.hidePassword') : t('auth.showPassword')"
:aria-pressed="show"
:aria-controls="id"
type="button"
@click="() => { show = !show }"
/>
</template>
</UInput>
</template>
<style scoped>
:deep(::-ms-reveal) {
display: none;
}
</style>
+4 -16
View File
@@ -38,7 +38,7 @@ async function submit() {
if (!canSubmit.value || loading.value) return
if (newPassword.value !== confirmPassword.value) {
toast.add({ title: t('password.mismatch'), color: 'error' })
toast.add({ title: t('auth.passwordMismatch'), color: 'error' })
return
}
@@ -101,14 +101,10 @@ async function submit() {
>
{{ t('password.current') }}
</label>
<UInput
<PasswordInput
id="current-password"
v-model="currentPassword"
type="password"
autocomplete="current-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
</div>
@@ -119,15 +115,11 @@ async function submit() {
>
{{ t('password.new') }}
</label>
<UInput
<PasswordInput
id="new-password"
v-model="newPassword"
type="password"
:placeholder="t('password.newPlaceholder')"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
<PasswordStrength :password="newPassword" />
</div>
@@ -139,14 +131,10 @@ async function submit() {
>
{{ t('password.confirmNew') }}
</label>
<UInput
<PasswordInput
id="confirm-new-password"
v-model="confirmPassword"
type="password"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
</div>
+3 -11
View File
@@ -22,7 +22,7 @@ const canSubmit = computed(() =>
onMounted(async () => {
const status = await fetchStatus()
if (!status.initialized) {
if (!status.initialized && !status.legacyMode) {
await router.replace('/setup')
return
}
@@ -118,15 +118,11 @@ async function submit() {
>
{{ t('auth.password') }}
</label>
<UInput
<PasswordInput
id="register-password"
v-model="password"
type="password"
:placeholder="t('setup.passwordPlaceholder')"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
<PasswordStrength :password="password" />
</div>
@@ -138,15 +134,11 @@ async function submit() {
>
{{ t('auth.confirmPassword') }}
</label>
<UInput
<PasswordInput
id="register-confirm"
v-model="confirmPassword"
type="password"
:placeholder="t('setup.confirmPlaceholder')"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
</div>
+9 -11
View File
@@ -9,7 +9,8 @@ const { setup, migrate, fetchStatus } = useAuth()
const toast = useToast()
const { t } = useI18n()
const isMigrate = computed(() => route.query.migrate === '1')
const needsMigration = ref(false)
const isMigrate = computed(() => needsMigration.value || route.query.migrate === '1')
const username = ref('')
const password = ref('')
@@ -26,6 +27,11 @@ const canSubmit = computed(() =>
onMounted(async () => {
const status = await fetchStatus()
needsMigration.value = status.needsMigration
if (status.legacyMode && !status.needsMigration) {
await router.replace('/')
return
}
if (status.initialized && !status.needsMigration) {
await router.replace('/')
}
@@ -129,15 +135,11 @@ async function submit() {
>
{{ t('auth.password') }}
</label>
<UInput
<PasswordInput
id="setup-password"
v-model="password"
type="password"
:placeholder="t('setup.passwordPlaceholder')"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
<PasswordStrength :password="password" />
</div>
@@ -149,15 +151,11 @@ async function submit() {
>
{{ t('auth.confirmPassword') }}
</label>
<UInput
<PasswordInput
id="setup-confirm"
v-model="confirmPassword"
type="password"
:placeholder="t('setup.confirmPlaceholder')"
autocomplete="new-password"
size="lg"
class="w-full"
:ui="{ root: 'w-full' }"
/>
</div>