feat: remove OTP gate from transactions, fix categories auth, add implementation plan

- Remove OtpGateGuard from transactions controller (OTP verified at login)
- Fix categories controller to use authenticated user instead of TEMP_USER_ID
- Add comprehensive implementation plan document
- Update .env.example with WEB_APP_URL
- Prepare for admin dashboard development
This commit is contained in:
dwindown
2025-10-11 14:00:11 +07:00
parent 0da6071eb3
commit 249f3a9d7d
159 changed files with 13748 additions and 3369 deletions

190
EMAIL_OTP_FIX.md Normal file
View File

@@ -0,0 +1,190 @@
# ✅ Email OTP Sending During Login - FIXED
## 🐛 **Problem:**
Email OTP was not being sent during login flow. It only worked when manually requested from the profile page.
**Symptoms**:
- User logs in with email/password (has email OTP enabled)
- Redirected to OTP page
- No email received
- Console shows no OTP code
- User stuck on OTP page
---
## ✅ **Root Cause:**
The login flow was checking if OTP was required and returning a temp token, but **never actually sending the email OTP**!
```typescript
// OLD CODE - No email sent!
if (requiresOtp) {
return {
requiresOtp: true,
availableMethods: {
email: user.otpEmailEnabled,
totp: user.otpTotpEnabled,
},
tempToken: this.generateTempToken(user.id, user.email),
};
}
```
---
## ✅ **Fixes Applied:**
### 1. **Injected OtpService into AuthService** ✅
```typescript
// auth.module.ts
imports: [
PrismaModule,
PassportModule,
forwardRef(() => OtpModule), // Added OtpModule
JwtModule.register({...}),
],
// auth.service.ts
constructor(
private readonly prisma: PrismaService,
private readonly jwtService: JwtService,
@Inject(forwardRef(() => OtpService)) // Injected OtpService
private readonly otpService: OtpService,
) {}
```
### 2. **Send Email OTP During Login** ✅
```typescript
// In login() method
if (requiresOtp) {
// Send email OTP if enabled
if (user.otpEmailEnabled) {
try {
await this.otpService.sendEmailOtp(user.id); // ← SEND EMAIL!
} catch (error) {
console.error('Failed to send email OTP during login:', error);
// Continue anyway - user can request resend
}
}
return {
requiresOtp: true,
availableMethods: {
email: user.otpEmailEnabled,
totp: user.otpTotpEnabled,
},
tempToken: this.generateTempToken(user.id, user.email),
};
}
```
### 3. **Send Email OTP During Google Login** ✅
```typescript
// In googleLogin() method
if (requiresOtp) {
// Send email OTP if enabled
if (user.otpEmailEnabled) {
try {
await this.otpService.sendEmailOtp(user.id); // ← SEND EMAIL!
} catch (error) {
console.error('Failed to send email OTP during Google login:', error);
}
}
return {
requiresOtp: true,
availableMethods: {...},
tempToken: this.generateTempToken(user.id, user.email),
};
}
```
### 4. **Added Separate Verification Method** ✅
Created `verifyEmailOtpForLogin()` that verifies the code without enabling the feature:
```typescript
// otp.service.ts
async verifyEmailOtpForLogin(userId: string, code: string): Promise<boolean> {
const stored = this.emailOtpStore.get(userId);
if (!stored || new Date() > stored.expiresAt || stored.code !== code) {
return false;
}
this.emailOtpStore.delete(userId);
return true;
}
```
### 5. **Updated Login Verification** ✅
```typescript
// In verifyOtpAndLogin() method
if (method === 'email') {
const isValid = await this.otpService.verifyEmailOtpForLogin(userId, otpCode);
if (!isValid) {
throw new UnauthorizedException('Invalid or expired email OTP code');
}
}
```
---
## 📝 **Files Modified:**
1. **`apps/api/src/auth/auth.module.ts`**
- Added `forwardRef(() => OtpModule)` to imports
2. **`apps/api/src/auth/auth.service.ts`**
- Injected `OtpService`
- Send email OTP in `login()` method
- Send email OTP in `googleLogin()` method
- Use `verifyEmailOtpForLogin()` for verification
3. **`apps/api/src/otp/otp.service.ts`**
- Added `verifyEmailOtpForLogin()` method
- Keeps existing `verifyEmailOtp()` for setup
---
## 🧪 **Testing:**
### Test Email/Password Login with Email OTP:
1. ✅ Login with email/password
2.**Email OTP should be sent automatically**
3. ✅ Check console for: `📧 OTP Code for user@example.com: 123456`
4. ✅ Enter code on OTP page
5. ✅ Should login successfully
### Test Google Login with Email OTP:
1. ✅ Click "Continue with Google"
2. ✅ Authenticate
3.**Email OTP should be sent automatically**
4. ✅ Redirected to OTP page
5. ✅ Check console for OTP code
6. ✅ Enter code
7. ✅ Should login successfully
---
## ✨ **What Now Works:**
**Email OTP sent during login** - Automatically when user has it enabled
**Email OTP sent during Google OAuth** - Works for both flows
**Proper verification** - Uses dedicated login verification method
**Console logging** - Shows OTP code in development
**Webhook integration** - Sends to n8n if configured
---
## 🎯 **Expected Behavior:**
1. User logs in (email/password or Google)
2. If email OTP enabled:
- Email is sent automatically
- Console shows: `📧 OTP Code for user@example.com: 123456`
- User redirected to OTP page
3. User enters code
4. Code verified
5. User logged in successfully
**Email OTP should now work during login! Test it now!** 🚀