feat: email verification, merchant/store password reset, seed gap fix
Some checks failed
Some checks failed
- Add EmailVerificationToken and UserPasswordResetToken models with migration - Add email verification flow: verify-email page route, resend-verification API - Block login for unverified users (EmailNotVerifiedException in auth_service) - Add forgot-password/reset-password endpoints for merchant and store auth - Add "Forgot Password?" links to merchant and store login pages - Send welcome email with verification link on merchant creation - Seed email_verification and merchant_password_reset email templates - Fix db-reset Makefile to run all init-prod seed scripts - Add UserAuthService to satisfy architecture validation rules - Add 52 new tests (unit + integration) with full coverage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -86,18 +86,48 @@
|
||||
|
||||
<hr class="my-8" />
|
||||
|
||||
<p class="mt-4">
|
||||
<a class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline"
|
||||
href="#">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="/">
|
||||
← Back to Platform
|
||||
</a>
|
||||
</p>
|
||||
<!-- Forgot Password Form -->
|
||||
<div x-show="showForgotPassword" x-transition>
|
||||
<h2 class="mb-4 text-lg font-semibold text-gray-700 dark:text-gray-200">Reset Password</h2>
|
||||
<p class="mb-4 text-sm text-gray-600 dark:text-gray-400">Enter your email address and we'll send you a link to reset your password.</p>
|
||||
<form @submit.prevent="handleForgotPassword">
|
||||
<label class="block text-sm">
|
||||
<span class="text-gray-700 dark:text-gray-400">Email</span>
|
||||
<input x-model="forgotPasswordEmail"
|
||||
:disabled="forgotPasswordLoading"
|
||||
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input"
|
||||
placeholder="you@example.com"
|
||||
type="email"
|
||||
required />
|
||||
</label>
|
||||
<button type="submit" :disabled="forgotPasswordLoading"
|
||||
class="block w-full px-4 py-2 mt-4 text-sm font-medium leading-5 text-center text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50">
|
||||
<span x-show="!forgotPasswordLoading">Send Reset Link</span>
|
||||
<span x-show="forgotPasswordLoading">Sending...</span>
|
||||
</button>
|
||||
</form>
|
||||
<p class="mt-4">
|
||||
<a @click.prevent="showForgotPassword = false"
|
||||
class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline cursor-pointer">
|
||||
← Back to Login
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div x-show="!showForgotPassword">
|
||||
<p class="mt-4">
|
||||
<a @click.prevent="showForgotPassword = true"
|
||||
class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline cursor-pointer">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="/">
|
||||
← Back to Platform
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -119,18 +119,48 @@
|
||||
|
||||
<hr class="my-8" />
|
||||
|
||||
<p class="mt-4">
|
||||
<a class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline"
|
||||
href="#">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="/">
|
||||
← Back to Platform
|
||||
</a>
|
||||
</p>
|
||||
<!-- Forgot Password Form -->
|
||||
<div x-show="showForgotPassword" x-transition>
|
||||
<h2 class="mb-4 text-lg font-semibold text-gray-700 dark:text-gray-200">Reset Password</h2>
|
||||
<p class="mb-4 text-sm text-gray-600 dark:text-gray-400">Enter your email address and we'll send you a link to reset your password.</p>
|
||||
<form @submit.prevent="handleForgotPassword">
|
||||
<label class="block text-sm">
|
||||
<span class="text-gray-700 dark:text-gray-400">Email</span>
|
||||
<input x-model="forgotPasswordEmail"
|
||||
:disabled="forgotPasswordLoading"
|
||||
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input"
|
||||
placeholder="you@example.com"
|
||||
type="email"
|
||||
required />
|
||||
</label>
|
||||
<button type="submit" :disabled="forgotPasswordLoading"
|
||||
class="block w-full px-4 py-2 mt-4 text-sm font-medium leading-5 text-center text-white transition-colors duration-150 bg-purple-600 border border-transparent rounded-lg hover:bg-purple-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50">
|
||||
<span x-show="!forgotPasswordLoading">Send Reset Link</span>
|
||||
<span x-show="forgotPasswordLoading">Sending...</span>
|
||||
</button>
|
||||
</form>
|
||||
<p class="mt-4">
|
||||
<a @click.prevent="showForgotPassword = false"
|
||||
class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline cursor-pointer">
|
||||
← Back to Login
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div x-show="!showForgotPassword">
|
||||
<p class="mt-4">
|
||||
<a @click.prevent="showForgotPassword = true"
|
||||
class="text-sm font-medium text-purple-600 dark:text-purple-400 hover:underline cursor-pointer">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="/">
|
||||
← Back to Platform
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user