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:
133
RESEND_OTP_FIX.md
Normal file
133
RESEND_OTP_FIX.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 🔧 Resend OTP Fix - Public Endpoint
|
||||
|
||||
## 🐛 **Problem:**
|
||||
Resend OTP endpoint was failing with `ERR_CONNECTION_REFUSED` because:
|
||||
1. The entire `OtpController` has `@UseGuards(AuthGuard)` at class level
|
||||
2. The resend endpoint requires a temp token, not a full JWT
|
||||
3. AuthGuard was rejecting the request
|
||||
|
||||
## ✅ **Solution:**
|
||||
Made the resend endpoint public by:
|
||||
1. Adding `@Public()` decorator
|
||||
2. Updating `AuthGuard` to respect public routes
|
||||
3. Endpoint verifies temp token manually
|
||||
|
||||
---
|
||||
|
||||
## 📝 **Changes Made:**
|
||||
|
||||
### 1. **Updated OtpController** (`otp.controller.ts`):
|
||||
|
||||
```typescript
|
||||
// Added Public decorator
|
||||
export const IS_PUBLIC_KEY = 'isPublic';
|
||||
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
|
||||
|
||||
// Marked resend endpoint as public
|
||||
@Public()
|
||||
@Post('email/resend')
|
||||
async resendEmailOtp(@Body() body: { tempToken: string }) {
|
||||
try {
|
||||
// Verify temp token manually
|
||||
const payload = this.jwtService.verify(body.tempToken);
|
||||
|
||||
if (!payload.temp) {
|
||||
throw new UnauthorizedException('Invalid token type');
|
||||
}
|
||||
|
||||
const userId = payload.userId || payload.sub;
|
||||
|
||||
// Send OTP
|
||||
return this.otpService.sendEmailOtp(userId);
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException('Invalid or expired token');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. **Updated AuthGuard** (`auth.guard.ts`):
|
||||
|
||||
```typescript
|
||||
import { Reflector } from '@nestjs/core';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard extends PassportAuthGuard('jwt') {
|
||||
constructor(private reflector: Reflector) {
|
||||
super();
|
||||
}
|
||||
|
||||
canActivate(context: ExecutionContext) {
|
||||
// Check if route is marked as public
|
||||
const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
]);
|
||||
|
||||
if (isPublic) {
|
||||
return true; // Skip authentication
|
||||
}
|
||||
|
||||
return super.canActivate(context);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 **How It Works:**
|
||||
|
||||
1. **Frontend** calls `/api/otp/email/resend` with temp token
|
||||
2. **AuthGuard** checks for `@Public()` decorator
|
||||
3. **If public**: Skips JWT validation, allows request through
|
||||
4. **Endpoint** manually verifies temp token
|
||||
5. **Extracts** userId from temp token
|
||||
6. **Sends** OTP email
|
||||
7. **Returns** success
|
||||
|
||||
---
|
||||
|
||||
## 🧪 **Testing:**
|
||||
|
||||
### **Test Resend:**
|
||||
1. ✅ Login with email OTP enabled
|
||||
2. ✅ On OTP page, wait 30 seconds
|
||||
3. ✅ Click "Resend Code"
|
||||
4. ✅ **Should work now!**
|
||||
5. ✅ Check console for new OTP code
|
||||
6. ✅ Enter code and login
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ **Current Status:**
|
||||
|
||||
Backend needs to restart to apply changes. If backend is not responding:
|
||||
|
||||
```bash
|
||||
# Kill existing process
|
||||
pkill -f "nest start"
|
||||
|
||||
# Restart
|
||||
cd apps/api
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 **Files Modified:**
|
||||
|
||||
1. **`apps/api/src/otp/otp.controller.ts`**
|
||||
- Added `Public` decorator
|
||||
- Marked `email/resend` as public
|
||||
- Injected `JwtService`
|
||||
|
||||
2. **`apps/api/src/auth/auth.guard.ts`**
|
||||
- Injected `Reflector`
|
||||
- Added public route check
|
||||
- Skip auth for public routes
|
||||
|
||||
3. **`apps/web/src/components/pages/OtpVerification.tsx`**
|
||||
- Already updated to use `/api/otp/email/resend`
|
||||
|
||||
---
|
||||
|
||||
**Once backend restarts, resend should work!** 🚀
|
||||
Reference in New Issue
Block a user