This commit is contained in:
parent
29aa5c2f36
commit
d0b672ac15
312
EMAIL_SETUP.md
Normal file
312
EMAIL_SETUP.md
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
# Email Configuration Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
The Brand Master application supports sending transactional emails for:
|
||||||
|
- Password reset PINs
|
||||||
|
- Welcome emails for new users
|
||||||
|
- Order confirmations (future)
|
||||||
|
- Contact form notifications (future)
|
||||||
|
|
||||||
|
## Email Service Options
|
||||||
|
|
||||||
|
### Option 1: Gmail SMTP (Recommended for Testing)
|
||||||
|
|
||||||
|
1. **Create App Password** (if using Gmail with 2FA):
|
||||||
|
- Go to Google Account Settings → Security
|
||||||
|
- Enable 2-Factor Authentication
|
||||||
|
- Go to "App passwords"
|
||||||
|
- Generate app password for "Mail"
|
||||||
|
- Copy the 16-character password
|
||||||
|
|
||||||
|
2. **Configure Environment Variables**:
|
||||||
|
```bash
|
||||||
|
SMTP_HOST=smtp.gmail.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USERNAME=your-email@gmail.com
|
||||||
|
SMTP_PASSWORD=your-app-password
|
||||||
|
SMTP_FROM=noreply@brand-master.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: SendGrid (Recommended for Production)
|
||||||
|
|
||||||
|
1. **Create SendGrid Account**:
|
||||||
|
- Sign up at https://sendgrid.com
|
||||||
|
- Verify your sender email
|
||||||
|
- Create API key
|
||||||
|
|
||||||
|
2. **Configure Environment Variables**:
|
||||||
|
```bash
|
||||||
|
SMTP_HOST=smtp.sendgrid.net
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USERNAME=apikey
|
||||||
|
SMTP_PASSWORD=your-sendgrid-api-key
|
||||||
|
SMTP_FROM=noreply@brand-master.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: Amazon SES (Production - Most Reliable)
|
||||||
|
|
||||||
|
1. **Setup SES**:
|
||||||
|
- Sign up for AWS SES
|
||||||
|
- Verify your domain or email
|
||||||
|
- Get SMTP credentials
|
||||||
|
|
||||||
|
2. **Configure Environment Variables**:
|
||||||
|
```bash
|
||||||
|
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USERNAME=your-ses-smtp-username
|
||||||
|
SMTP_PASSWORD=your-ses-smtp-password
|
||||||
|
SMTP_FROM=noreply@brand-master.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Kubernetes Deployment Configuration
|
||||||
|
|
||||||
|
### Method 1: Update values.yaml (Recommended)
|
||||||
|
|
||||||
|
Edit `brand-master-chart/values.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
backend:
|
||||||
|
env:
|
||||||
|
# Existing vars...
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: "smtp.gmail.com"
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: "587"
|
||||||
|
- name: SMTP_USERNAME
|
||||||
|
value: "your-email@gmail.com"
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
value: "your-app-password" # Use secrets in production!
|
||||||
|
- name: SMTP_FROM
|
||||||
|
value: "noreply@brand-master.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 2: Use Kubernetes Secret (Production)
|
||||||
|
|
||||||
|
1. **Create Secret**:
|
||||||
|
```bash
|
||||||
|
kubectl create secret generic brand-master-email \
|
||||||
|
--from-literal=smtp-username=your-email@gmail.com \
|
||||||
|
--from-literal=smtp-password=your-app-password \
|
||||||
|
-n my-apps
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Update Deployment** (`brand-master-chart/templates/backend-deployment.yaml`):
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
# ... existing env vars ...
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: "smtp.gmail.com"
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: "587"
|
||||||
|
- name: SMTP_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: brand-master-email
|
||||||
|
key: smtp-username
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: brand-master-email
|
||||||
|
key: smtp-password
|
||||||
|
- name: SMTP_FROM
|
||||||
|
value: "noreply@brand-master.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Local Development (.env file)
|
||||||
|
|
||||||
|
Create `backend/.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL=postgresql://brand_master_user:your_password@localhost/brand_master_db
|
||||||
|
JWT_SECRET_KEY=your-secret-key
|
||||||
|
FRONTEND_URL=http://localhost:5173
|
||||||
|
BACKEND_URL=http://localhost:8000
|
||||||
|
|
||||||
|
# Email Configuration
|
||||||
|
SMTP_HOST=smtp.gmail.com
|
||||||
|
SMTP_PORT=587
|
||||||
|
SMTP_USERNAME=your-email@gmail.com
|
||||||
|
SMTP_PASSWORD=your-app-password
|
||||||
|
SMTP_FROM=noreply@brand-master.com
|
||||||
|
|
||||||
|
# Admin Credentials
|
||||||
|
ADMIN_EMAIL=admin@brandmaster.com
|
||||||
|
ADMIN_PASSWORD=Admin123!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Email Functionality
|
||||||
|
|
||||||
|
### Test Password Reset
|
||||||
|
|
||||||
|
1. **Trigger Password Reset**:
|
||||||
|
```bash
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/request-reset-pin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"email": "user@example.com"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Email**:
|
||||||
|
- User should receive email with 6-digit PIN
|
||||||
|
- PIN expires in 15 minutes
|
||||||
|
|
||||||
|
3. **Reset Password**:
|
||||||
|
```bash
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/reset-password-with-pin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"email": "user@example.com",
|
||||||
|
"pin": "123456",
|
||||||
|
"new_password": "NewPassword123!"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Welcome Email
|
||||||
|
|
||||||
|
1. **Register New User**:
|
||||||
|
```bash
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/register \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"email": "newuser@example.com",
|
||||||
|
"full_name": "Test User",
|
||||||
|
"password": "password123"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check Email**:
|
||||||
|
- User should receive welcome email
|
||||||
|
|
||||||
|
### Check Backend Logs
|
||||||
|
|
||||||
|
If emails aren't being sent:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View backend logs
|
||||||
|
kubectl logs -n my-apps deployment/brand-master-backend -f
|
||||||
|
|
||||||
|
# Look for:
|
||||||
|
# ✅ Email sent successfully to user@example.com
|
||||||
|
# OR
|
||||||
|
# ⚠️ SMTP not configured. Email would have been sent to: user@example.com
|
||||||
|
# OR
|
||||||
|
# ❌ Failed to send email to user@example.com: <error details>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Issue: "SMTP not configured" message
|
||||||
|
|
||||||
|
**Problem**: SMTP environment variables not set
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
```bash
|
||||||
|
# Check if variables are set in pod
|
||||||
|
kubectl exec -n my-apps deployment/brand-master-backend -- env | grep SMTP
|
||||||
|
|
||||||
|
# Should show:
|
||||||
|
# SMTP_HOST=smtp.gmail.com
|
||||||
|
# SMTP_PORT=587
|
||||||
|
# SMTP_USERNAME=your-email@gmail.com
|
||||||
|
# SMTP_PASSWORD=***
|
||||||
|
# SMTP_FROM=noreply@brand-master.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: "Authentication failed" error
|
||||||
|
|
||||||
|
**Problem**: Wrong credentials or app password required
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
- For Gmail: Use App Password, not account password
|
||||||
|
- Verify credentials are correct
|
||||||
|
- Check if 2FA is enabled (required for App Passwords)
|
||||||
|
|
||||||
|
### Issue: "Connection refused" error
|
||||||
|
|
||||||
|
**Problem**: Wrong SMTP host or port, or firewall blocking
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
- Verify SMTP_HOST and SMTP_PORT are correct
|
||||||
|
- Check Kubernetes network policies
|
||||||
|
- Test SMTP connection from pod:
|
||||||
|
```bash
|
||||||
|
kubectl exec -n my-apps deployment/brand-master-backend -- \
|
||||||
|
nc -zv smtp.gmail.com 587
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Emails go to spam
|
||||||
|
|
||||||
|
**Problem**: Missing SPF/DKIM records or sender reputation
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
- Use verified domain with proper DNS records
|
||||||
|
- Use SendGrid or SES for production
|
||||||
|
- Add SPF record: `v=spf1 include:_spf.google.com ~all`
|
||||||
|
- Setup DKIM signing
|
||||||
|
|
||||||
|
## Email Templates
|
||||||
|
|
||||||
|
Email templates are in `backend/app/services/email.py`:
|
||||||
|
|
||||||
|
- `send_password_reset_pin()` - Password reset with PIN
|
||||||
|
- `send_welcome_email()` - Welcome new users
|
||||||
|
|
||||||
|
To customize:
|
||||||
|
1. Edit template in `email.py`
|
||||||
|
2. Rebuild backend image
|
||||||
|
3. Redeploy
|
||||||
|
|
||||||
|
## Production Best Practices
|
||||||
|
|
||||||
|
1. ✅ **Use Kubernetes Secrets** for credentials
|
||||||
|
2. ✅ **Use dedicated email service** (SendGrid, SES)
|
||||||
|
3. ✅ **Setup SPF/DKIM** for deliverability
|
||||||
|
4. ✅ **Monitor email sending** (logs, metrics)
|
||||||
|
5. ✅ **Implement rate limiting** to prevent abuse
|
||||||
|
6. ✅ **Use verified sender domain**
|
||||||
|
7. ✅ **Add unsubscribe links** for marketing emails
|
||||||
|
8. ✅ **Keep templates professional** and branded
|
||||||
|
|
||||||
|
## Quick Setup for Testing (Gmail)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Update values.yaml
|
||||||
|
nano brand-master-chart/values.yaml
|
||||||
|
|
||||||
|
# Add under backend.env:
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: "smtp.gmail.com"
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: "587"
|
||||||
|
- name: SMTP_USERNAME
|
||||||
|
value: "your-email@gmail.com"
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
value: "your-16-char-app-password"
|
||||||
|
- name: SMTP_FROM
|
||||||
|
value: "Brand Master <noreply@brand-master.com>"
|
||||||
|
|
||||||
|
# 2. Redeploy
|
||||||
|
cd brand-master-chart
|
||||||
|
helm upgrade brand-master . --namespace my-apps --wait
|
||||||
|
|
||||||
|
# 3. Test
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/request-reset-pin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"email": "your-test-email@gmail.com"}'
|
||||||
|
|
||||||
|
# 4. Check email inbox
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If emails still don't work:
|
||||||
|
1. Check backend logs for error messages
|
||||||
|
2. Verify SMTP credentials
|
||||||
|
3. Test SMTP connection manually
|
||||||
|
4. Check spam folder
|
||||||
|
5. Try different email provider
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status**: Email service implemented and ready to configure
|
||||||
|
**Last Updated**: May 8, 2026
|
||||||
304
PASSWORD_RESET_GUIDE.md
Normal file
304
PASSWORD_RESET_GUIDE.md
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
# Password Reset with Email PIN - Implementation Summary
|
||||||
|
|
||||||
|
## What Was Implemented
|
||||||
|
|
||||||
|
### 1. Email Service Module ✅
|
||||||
|
**File**: `backend/app/services/email.py`
|
||||||
|
|
||||||
|
**Features**:
|
||||||
|
- `send_email()` - Generic SMTP email sender
|
||||||
|
- `send_password_reset_pin()` - Sends 6-digit PIN with HTML/plain text template
|
||||||
|
- `send_welcome_email()` - Welcome new users
|
||||||
|
- Graceful fallback: Prints to console if SMTP not configured
|
||||||
|
- Professional HTML email templates with branding
|
||||||
|
|
||||||
|
**Template Highlights**:
|
||||||
|
- Beautiful HTML design with Brand Master branding
|
||||||
|
- 6-digit PIN displayed prominently
|
||||||
|
- 15-minute expiration timer
|
||||||
|
- Instructions for password reset
|
||||||
|
- Responsive design
|
||||||
|
- Plain text fallback
|
||||||
|
|
||||||
|
### 2. Auth Router Integration ✅
|
||||||
|
**File**: `backend/app/routers/auth.py`
|
||||||
|
|
||||||
|
**Changes**:
|
||||||
|
- Imported email service functions
|
||||||
|
- Updated `request_reset_pin()` to send email instead of just printing
|
||||||
|
- Updated `register()` to send welcome email to new users
|
||||||
|
- Added error handling (non-blocking - won't fail if email fails)
|
||||||
|
- Removed PIN from API response (security fix)
|
||||||
|
|
||||||
|
**Flow**:
|
||||||
|
1. User requests password reset with email
|
||||||
|
2. System generates 6-digit PIN
|
||||||
|
3. Stores PIN in database with 15-minute expiration
|
||||||
|
4. **Sends PIN to user's email** (new!)
|
||||||
|
5. Falls back to console print if SMTP not configured
|
||||||
|
6. User enters PIN and new password
|
||||||
|
7. System validates PIN and updates password
|
||||||
|
|
||||||
|
### 3. Configuration Guide ✅
|
||||||
|
**File**: `EMAIL_SETUP.md`
|
||||||
|
|
||||||
|
**Includes**:
|
||||||
|
- 3 email provider options (Gmail, SendGrid, AWS SES)
|
||||||
|
- Step-by-step setup for each provider
|
||||||
|
- Kubernetes deployment configuration
|
||||||
|
- Secret management (production best practices)
|
||||||
|
- Testing instructions
|
||||||
|
- Troubleshooting guide
|
||||||
|
- Production checklist
|
||||||
|
|
||||||
|
### 4. Quick Fix Deployment Script ✅
|
||||||
|
**File**: `quick-fix.bat`
|
||||||
|
|
||||||
|
**Automates**:
|
||||||
|
- Applies both database migrations (007, 008)
|
||||||
|
- Builds backend and frontend Docker images
|
||||||
|
- Pushes to Harbor registry
|
||||||
|
- Deploys via Helm
|
||||||
|
- Shows next steps and instructions
|
||||||
|
|
||||||
|
## What You Need to Do
|
||||||
|
|
||||||
|
### REQUIRED Steps
|
||||||
|
|
||||||
|
#### 1. Apply Database Migrations (CRITICAL)
|
||||||
|
The system currently has errors because migrations aren't applied:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option A: Use quick-fix script (does everything)
|
||||||
|
quick-fix.bat
|
||||||
|
|
||||||
|
# Option B: Apply migrations manually
|
||||||
|
apply-migration.bat 007_enhance_contact_messages.sql
|
||||||
|
apply-migration.bat 008_add_username_to_users.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**These migrations fix**:
|
||||||
|
- ❌ "column full_name does not exist" → ✅ Renames name → full_name
|
||||||
|
- ❌ "column username does not exist" → ✅ Adds username column
|
||||||
|
|
||||||
|
#### 2. Configure Email (for password reset to work)
|
||||||
|
|
||||||
|
**Quick Setup (Gmail)**:
|
||||||
|
|
||||||
|
1. Get Gmail App Password:
|
||||||
|
- Go to https://myaccount.google.com/apppasswords
|
||||||
|
- Generate password for "Mail"
|
||||||
|
- Copy 16-character password
|
||||||
|
|
||||||
|
2. Update `brand-master-chart/values.yaml`:
|
||||||
|
```yaml
|
||||||
|
backend:
|
||||||
|
env:
|
||||||
|
# ... existing vars ...
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: "smtp.gmail.com"
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: "587"
|
||||||
|
- name: SMTP_USERNAME
|
||||||
|
value: "your-email@gmail.com"
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
value: "abcd efgh ijkl mnop" # Your 16-char app password
|
||||||
|
- name: SMTP_FROM
|
||||||
|
value: "Brand Master <noreply@brand-master.com>"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Redeploy:
|
||||||
|
```bash
|
||||||
|
cd brand-master-chart
|
||||||
|
helm upgrade brand-master . --namespace my-apps --wait
|
||||||
|
```
|
||||||
|
|
||||||
|
**Read [EMAIL_SETUP.md](EMAIL_SETUP.md) for**:
|
||||||
|
- Other email providers (SendGrid, AWS SES)
|
||||||
|
- Production setup with Kubernetes Secrets
|
||||||
|
- Troubleshooting guide
|
||||||
|
|
||||||
|
### OPTIONAL Steps
|
||||||
|
|
||||||
|
#### 3. Test Email Functionality
|
||||||
|
|
||||||
|
**Test Password Reset**:
|
||||||
|
```bash
|
||||||
|
# Request PIN
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/request-reset-pin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"email": "your-test-email@gmail.com"}'
|
||||||
|
|
||||||
|
# Check your email for 6-digit PIN
|
||||||
|
|
||||||
|
# Reset password
|
||||||
|
curl -X POST https://api-brand-master.dvirlabs.com/api/auth/reset-password-with-pin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"email": "your-test-email@gmail.com",
|
||||||
|
"pin": "123456",
|
||||||
|
"new_password": "NewPassword123!"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Or test via UI**:
|
||||||
|
1. Go to https://brand-master.dvirlabs.com/login
|
||||||
|
2. Click "Forgot Password?"
|
||||||
|
3. Enter email
|
||||||
|
4. Check inbox for PIN
|
||||||
|
5. Enter PIN and new password
|
||||||
|
|
||||||
|
#### 4. Monitor Email Sending
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View backend logs
|
||||||
|
kubectl logs -n my-apps deployment/brand-master-backend -f
|
||||||
|
|
||||||
|
# Look for:
|
||||||
|
# ✅ Email sent successfully to user@example.com
|
||||||
|
# ⚠️ SMTP not configured. Email would have been sent to: ...
|
||||||
|
# ❌ Failed to send email: <error>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current Status
|
||||||
|
|
||||||
|
| Feature | Status | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| Email service code | ✅ Complete | `backend/app/services/email.py` created |
|
||||||
|
| Password reset PIN email | ✅ Complete | Sends HTML email with 6-digit PIN |
|
||||||
|
| Welcome email | ✅ Complete | Sent on new user registration |
|
||||||
|
| Auth router integration | ✅ Complete | Email functions called in endpoints |
|
||||||
|
| Configuration guide | ✅ Complete | See `EMAIL_SETUP.md` |
|
||||||
|
| Deployment script | ✅ Complete | `quick-fix.bat` |
|
||||||
|
| Database migrations | ⚠️ **NOT APPLIED** | Must run migrations! |
|
||||||
|
| SMTP configuration | ⚠️ **NOT CONFIGURED** | Emails print to console until configured |
|
||||||
|
| Production deployment | ⚠️ Pending | Need to rebuild/redeploy |
|
||||||
|
|
||||||
|
## How It Works Now
|
||||||
|
|
||||||
|
### Without SMTP Configured (Current State)
|
||||||
|
|
||||||
|
**What happens**:
|
||||||
|
1. User requests password reset
|
||||||
|
2. System generates PIN
|
||||||
|
3. **Email service prints to console**:
|
||||||
|
```
|
||||||
|
⚠️ SMTP not configured. Email would have been sent to: user@example.com
|
||||||
|
Subject: Brand Master - Password Reset PIN
|
||||||
|
Body: Your PIN is: 123456
|
||||||
|
```
|
||||||
|
4. You check backend logs for the PIN
|
||||||
|
5. User can still reset password with the PIN
|
||||||
|
|
||||||
|
**This is fine for testing but not production!**
|
||||||
|
|
||||||
|
### With SMTP Configured (After Setup)
|
||||||
|
|
||||||
|
**What happens**:
|
||||||
|
1. User requests password reset
|
||||||
|
2. System generates PIN
|
||||||
|
3. **Email sent to user's inbox** ✅
|
||||||
|
4. User receives beautiful HTML email with PIN
|
||||||
|
5. User resets password (no need to check logs)
|
||||||
|
|
||||||
|
## Files Changed
|
||||||
|
|
||||||
|
### Created
|
||||||
|
- ✅ `backend/app/services/email.py` - Email service module
|
||||||
|
- ✅ `EMAIL_SETUP.md` - Email configuration guide
|
||||||
|
- ✅ `quick-fix.bat` - Automated deployment script
|
||||||
|
- ✅ `PASSWORD_RESET_GUIDE.md` - This file
|
||||||
|
|
||||||
|
### Modified
|
||||||
|
- ✅ `backend/app/routers/auth.py` - Integrated email service
|
||||||
|
|
||||||
|
### Ready to Apply
|
||||||
|
- ⚠️ `backend/migrations/007_enhance_contact_messages.sql`
|
||||||
|
- ⚠️ `backend/migrations/008_add_username_to_users.sql`
|
||||||
|
|
||||||
|
## Quick Start Commands
|
||||||
|
|
||||||
|
### Full Automated Deployment
|
||||||
|
```bash
|
||||||
|
# This does everything: migrations + build + deploy
|
||||||
|
quick-fix.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Step-by-Step
|
||||||
|
```bash
|
||||||
|
# 1. Apply migrations
|
||||||
|
apply-migration.bat 007_enhance_contact_messages.sql
|
||||||
|
apply-migration.bat 008_add_username_to_users.sql
|
||||||
|
|
||||||
|
# 2. Build images
|
||||||
|
cd backend && docker build -t harbor.dvirlabs.com/my-apps/brand-master-backend:latest . && cd ..
|
||||||
|
cd frontend && docker build -t harbor.dvirlabs.com/my-apps/brand-master-frontend:latest . && cd ..
|
||||||
|
|
||||||
|
# 3. Push images
|
||||||
|
docker push harbor.dvirlabs.com/my-apps/brand-master-backend:latest
|
||||||
|
docker push harbor.dvirlabs.com/my-apps/brand-master-frontend:latest
|
||||||
|
|
||||||
|
# 4. Deploy
|
||||||
|
cd brand-master-chart
|
||||||
|
helm upgrade brand-master . --namespace my-apps --wait
|
||||||
|
```
|
||||||
|
|
||||||
|
## Email Provider Recommendations
|
||||||
|
|
||||||
|
| Provider | Best For | Cost | Setup Difficulty |
|
||||||
|
|----------|----------|------|------------------|
|
||||||
|
| **Gmail** | Testing, Development | Free | Easy (App Password) |
|
||||||
|
| **SendGrid** | Production (Small) | Free tier: 100 emails/day | Medium |
|
||||||
|
| **AWS SES** | Production (Large) | $0.10 per 1000 emails | Medium-Hard |
|
||||||
|
| **Mailgun** | Production | Free tier: 5000 emails/month | Medium |
|
||||||
|
|
||||||
|
**My Recommendation**:
|
||||||
|
- **For testing now**: Gmail (5 minutes to setup)
|
||||||
|
- **For production later**: SendGrid or AWS SES (better deliverability)
|
||||||
|
|
||||||
|
## Testing Checklist
|
||||||
|
|
||||||
|
After deployment:
|
||||||
|
|
||||||
|
- [ ] Can submit contact form without errors
|
||||||
|
- [ ] Can register with username and phone
|
||||||
|
- [ ] Can login with email, username, OR phone
|
||||||
|
- [ ] Can request password reset
|
||||||
|
- [ ] Receive PIN email (or see in logs if SMTP not configured)
|
||||||
|
- [ ] Can reset password with PIN
|
||||||
|
- [ ] PIN expires after 15 minutes
|
||||||
|
- [ ] Invalid PIN shows error
|
||||||
|
- [ ] Welcome email sent on registration
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Column full_name does not exist"
|
||||||
|
**Fix**: Run `apply-migration.bat 007_enhance_contact_messages.sql`
|
||||||
|
|
||||||
|
### "Column username does not exist"
|
||||||
|
**Fix**: Run `apply-migration.bat 008_add_username_to_users.sql`
|
||||||
|
|
||||||
|
### "SMTP not configured" in logs
|
||||||
|
**Fix**: Configure SMTP in `values.yaml` (see [EMAIL_SETUP.md](EMAIL_SETUP.md))
|
||||||
|
|
||||||
|
### PIN not received in email
|
||||||
|
**Fix**: Check backend logs for error message, verify SMTP credentials
|
||||||
|
|
||||||
|
### Emails go to spam
|
||||||
|
**Fix**: Use proper From address, setup SPF/DKIM, or use SendGrid/SES
|
||||||
|
|
||||||
|
## Next Features (Future)
|
||||||
|
|
||||||
|
Possible enhancements:
|
||||||
|
- ✉️ Order confirmation emails
|
||||||
|
- ✉️ Shipping notification emails
|
||||||
|
- ✉️ Contact form notification to admin
|
||||||
|
- ✉️ Email templates customization UI
|
||||||
|
- 📊 Email delivery tracking
|
||||||
|
- 🎨 Email template builder
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Implementation Date**: January 2025
|
||||||
|
**Status**: Ready to deploy (migrations required)
|
||||||
|
**Documentation**: EMAIL_SETUP.md, API_DOCUMENTATION.md
|
||||||
@ -1,5 +1,20 @@
|
|||||||
@echo off
|
@echo off
|
||||||
REM Apply database migration 005 - Add password reset fields
|
REM Apply database migration script
|
||||||
|
REM Usage: apply-migration.bat <migration_filename>
|
||||||
|
|
||||||
|
if "%1"=="" (
|
||||||
|
echo ❌ Error: No migration file specified
|
||||||
|
echo Usage: apply-migration.bat ^<migration_filename^>
|
||||||
|
echo Example: apply-migration.bat 007_enhance_contact_messages.sql
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set MIGRATION_FILE=%1
|
||||||
|
|
||||||
|
if not exist "backend\migrations\%MIGRATION_FILE%" (
|
||||||
|
echo ❌ Migration file not found: backend\migrations\%MIGRATION_FILE%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
echo Getting database pod name...
|
echo Getting database pod name...
|
||||||
for /f "delims=" %%i in ('kubectl get pod -n my-apps -l app.kubernetes.io/component=db -o jsonpath^="{.items[0].metadata.name}"') do set DB_POD=%%i
|
for /f "delims=" %%i in ('kubectl get pod -n my-apps -l app.kubernetes.io/component=db -o jsonpath^="{.items[0].metadata.name}"') do set DB_POD=%%i
|
||||||
@ -10,17 +25,17 @@ if "%DB_POD%"=="" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
echo 📦 Database pod: %DB_POD%
|
echo 📦 Database pod: %DB_POD%
|
||||||
echo 📝 Applying migration 005_add_password_reset_fields.sql...
|
echo 📝 Applying migration: %MIGRATION_FILE%...
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
REM Copy migration file to pod
|
REM Copy migration file to pod
|
||||||
kubectl cp backend/migrations/005_add_password_reset_fields.sql my-apps/%DB_POD%:/tmp/migration.sql
|
kubectl cp backend/migrations/%MIGRATION_FILE% my-apps/%DB_POD%:/tmp/migration.sql
|
||||||
|
|
||||||
REM Execute migration
|
REM Execute migration
|
||||||
kubectl exec -n my-apps %DB_POD% -- psql -U brand_master_user -d brand_master_db -f /tmp/migration.sql
|
kubectl exec -n my-apps %DB_POD% -- psql -U brand_master_user -d brand_master_db -f /tmp/migration.sql
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ✅ Migration applied successfully!
|
echo ✅ Migration %MIGRATION_FILE% applied successfully!
|
||||||
echo.
|
echo.
|
||||||
echo 🔄 Restarting backend pod to pick up changes...
|
echo 🔄 Restarting backend pod to pick up changes...
|
||||||
kubectl delete pod -n my-apps -l app.kubernetes.io/component=backend
|
kubectl delete pod -n my-apps -l app.kubernetes.io/component=backend
|
||||||
|
|||||||
@ -15,6 +15,7 @@ from app.services.auth import (
|
|||||||
verify_password,
|
verify_password,
|
||||||
get_current_user,
|
get_current_user,
|
||||||
)
|
)
|
||||||
|
from app.services.email import send_password_reset_pin, send_welcome_email
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/auth", tags=["auth"])
|
router = APIRouter(prefix="/api/auth", tags=["auth"])
|
||||||
@ -42,16 +43,43 @@ def register(user: UserCreate, db: Session = Depends(get_db)):
|
|||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail="Email already registered",
|
detail="Email already registered",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check if username is already taken
|
||||||
|
if user.username:
|
||||||
|
existing_username = db.query(User).filter(User.username == user.username).first()
|
||||||
|
if existing_username:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Username already taken",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if phone is already taken
|
||||||
|
if user.phone:
|
||||||
|
existing_phone = db.query(User).filter(User.phone == user.phone).first()
|
||||||
|
if existing_phone:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Phone number already registered",
|
||||||
|
)
|
||||||
|
|
||||||
hashed_password = get_password_hash(user.password)
|
hashed_password = get_password_hash(user.password)
|
||||||
db_user = User(
|
db_user = User(
|
||||||
email=user.email,
|
email=user.email,
|
||||||
|
username=user.username,
|
||||||
|
phone=user.phone,
|
||||||
full_name=user.full_name,
|
full_name=user.full_name,
|
||||||
hashed_password=hashed_password,
|
hashed_password=hashed_password,
|
||||||
)
|
)
|
||||||
db.add(db_user)
|
db.add(db_user)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(db_user)
|
db.refresh(db_user)
|
||||||
|
|
||||||
|
# Send welcome email (non-blocking - don't fail registration if email fails)
|
||||||
|
try:
|
||||||
|
send_welcome_email(user.email, user.full_name)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to send welcome email: {e}")
|
||||||
|
|
||||||
return db_user
|
return db_user
|
||||||
|
|
||||||
|
|
||||||
@ -132,14 +160,16 @@ def reset_password(request: ResetPasswordRequest, db: Session = Depends(get_db))
|
|||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
detail="User not found",
|
detail="User not found",
|
||||||
)
|
Send PIN via email
|
||||||
|
email_sent = send_password_reset_pin(request.email, pin, expires_minutes=15)
|
||||||
|
|
||||||
# Update password
|
if not email_sent:
|
||||||
user.hashed_password = get_password_hash(request.new_password)
|
# If email sending fails, still print to console for development
|
||||||
db.commit()
|
print(f"\n⚠️ Email not sent. Password Reset PIN for {request.email}: {pin}")
|
||||||
|
print(f"Expires at: {user.pin_expires_at}\n")
|
||||||
|
|
||||||
return {"message": "Password reset successful"}
|
return {
|
||||||
|
"message": "If the email exists, a PIN has been sent to your email",
|
||||||
|
|
||||||
@router.post("/request-reset-pin")
|
@router.post("/request-reset-pin")
|
||||||
def request_reset_pin(request: RequestPinRequest, db: Session = Depends(get_db)):
|
def request_reset_pin(request: RequestPinRequest, db: Session = Depends(get_db)):
|
||||||
|
|||||||
233
backend/app/services/email.py
Normal file
233
backend/app/services/email.py
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from typing import Optional
|
||||||
|
from app.config import settings
|
||||||
|
|
||||||
|
|
||||||
|
def send_email(
|
||||||
|
to_email: str,
|
||||||
|
subject: str,
|
||||||
|
body: str,
|
||||||
|
html_body: Optional[str] = None
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Send an email using SMTP configuration from settings.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
to_email: Recipient email address
|
||||||
|
subject: Email subject
|
||||||
|
body: Plain text body
|
||||||
|
html_body: Optional HTML body (if provided, will be sent as multipart)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if email sent successfully, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Create message
|
||||||
|
message = MIMEMultipart('alternative') if html_body else MIMEText(body, 'plain')
|
||||||
|
|
||||||
|
if html_body:
|
||||||
|
message['Subject'] = subject
|
||||||
|
message['From'] = settings.smtp_from
|
||||||
|
message['To'] = to_email
|
||||||
|
|
||||||
|
# Attach plain text and HTML versions
|
||||||
|
part1 = MIMEText(body, 'plain')
|
||||||
|
part2 = MIMEText(html_body, 'html')
|
||||||
|
message.attach(part1)
|
||||||
|
message.attach(part2)
|
||||||
|
else:
|
||||||
|
message['Subject'] = subject
|
||||||
|
message['From'] = settings.smtp_from
|
||||||
|
message['To'] = to_email
|
||||||
|
|
||||||
|
# Check if SMTP is configured
|
||||||
|
if not settings.smtp_username or not settings.smtp_password:
|
||||||
|
print(f"⚠️ SMTP not configured. Email would have been sent to: {to_email}")
|
||||||
|
print(f"Subject: {subject}")
|
||||||
|
print(f"Body:\n{body}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Connect to SMTP server
|
||||||
|
with smtplib.SMTP(settings.smtp_host, settings.smtp_port) as server:
|
||||||
|
server.starttls()
|
||||||
|
server.login(settings.smtp_username, settings.smtp_password)
|
||||||
|
server.send_message(message)
|
||||||
|
|
||||||
|
print(f"✅ Email sent successfully to {to_email}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Failed to send email to {to_email}: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def send_password_reset_pin(email: str, pin: str, expires_minutes: int = 15) -> bool:
|
||||||
|
"""
|
||||||
|
Send password reset PIN email.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email: User's email address
|
||||||
|
pin: 6-digit PIN code
|
||||||
|
expires_minutes: Minutes until PIN expires
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if email sent successfully
|
||||||
|
"""
|
||||||
|
subject = "Brand Master - Password Reset PIN"
|
||||||
|
|
||||||
|
# Plain text version
|
||||||
|
body = f"""
|
||||||
|
Hello,
|
||||||
|
|
||||||
|
You requested a password reset for your Brand Master account.
|
||||||
|
|
||||||
|
Your 6-digit PIN code is: {pin}
|
||||||
|
|
||||||
|
This PIN will expire in {expires_minutes} minutes.
|
||||||
|
|
||||||
|
To reset your password:
|
||||||
|
1. Go to the login page
|
||||||
|
2. Click "Forgot Password"
|
||||||
|
3. Enter this PIN when prompted
|
||||||
|
4. Create your new password
|
||||||
|
|
||||||
|
If you didn't request this reset, please ignore this email.
|
||||||
|
|
||||||
|
Best regards,
|
||||||
|
Brand Master Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
# HTML version
|
||||||
|
html_body = f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {{ font-family: Arial, sans-serif; line-height: 1.6; color: #333; }}
|
||||||
|
.container {{ max-width: 600px; margin: 0 auto; padding: 20px; }}
|
||||||
|
.header {{ background: #007bff; color: white; padding: 20px; text-align: center; border-radius: 5px 5px 0 0; }}
|
||||||
|
.content {{ background: #f9f9f9; padding: 30px; border-radius: 0 0 5px 5px; }}
|
||||||
|
.pin-box {{ background: white; padding: 20px; text-align: center; border: 2px solid #007bff; border-radius: 5px; margin: 20px 0; }}
|
||||||
|
.pin {{ font-size: 32px; font-weight: bold; color: #007bff; letter-spacing: 5px; }}
|
||||||
|
.warning {{ color: #dc3545; font-weight: bold; }}
|
||||||
|
.footer {{ text-align: center; color: #666; margin-top: 20px; font-size: 12px; }}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>Password Reset Request</h1>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>Hello,</p>
|
||||||
|
<p>You requested a password reset for your Brand Master account.</p>
|
||||||
|
|
||||||
|
<div class="pin-box">
|
||||||
|
<p style="margin: 0; font-size: 14px;">Your 6-digit PIN code is:</p>
|
||||||
|
<p class="pin">{pin}</p>
|
||||||
|
<p style="margin: 0; color: #666;">Expires in {expires_minutes} minutes</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><strong>To reset your password:</strong></p>
|
||||||
|
<ol>
|
||||||
|
<li>Go to the <a href="https://brand-master.dvirlabs.com/login">login page</a></li>
|
||||||
|
<li>Click "Forgot Password"</li>
|
||||||
|
<li>Enter this PIN when prompted</li>
|
||||||
|
<li>Create your new password</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p class="warning">⚠️ If you didn't request this reset, please ignore this email.</p>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p>This is an automated message from Brand Master. Please do not reply.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return send_email(email, subject, body, html_body)
|
||||||
|
|
||||||
|
|
||||||
|
def send_welcome_email(email: str, full_name: str) -> bool:
|
||||||
|
"""
|
||||||
|
Send welcome email to new users.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email: User's email address
|
||||||
|
full_name: User's full name
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if email sent successfully
|
||||||
|
"""
|
||||||
|
subject = "Welcome to Brand Master!"
|
||||||
|
|
||||||
|
body = f"""
|
||||||
|
Hello {full_name},
|
||||||
|
|
||||||
|
Welcome to Brand Master! Your account has been created successfully.
|
||||||
|
|
||||||
|
You can now:
|
||||||
|
- Browse our collection of premium shoes and apparel
|
||||||
|
- Add items to your wishlist
|
||||||
|
- Place orders with secure checkout
|
||||||
|
- Track your order history
|
||||||
|
|
||||||
|
Visit us at: https://brand-master.dvirlabs.com
|
||||||
|
|
||||||
|
Best regards,
|
||||||
|
Brand Master Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
html_body = f"""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {{ font-family: Arial, sans-serif; line-height: 1.6; color: #333; }}
|
||||||
|
.container {{ max-width: 600px; margin: 0 auto; padding: 20px; }}
|
||||||
|
.header {{ background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); color: white; padding: 30px; text-align: center; border-radius: 5px 5px 0 0; }}
|
||||||
|
.content {{ background: #f9f9f9; padding: 30px; border-radius: 0 0 5px 5px; }}
|
||||||
|
.button {{ display: inline-block; padding: 12px 30px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 20px 0; }}
|
||||||
|
.features {{ background: white; padding: 20px; border-radius: 5px; margin: 20px 0; }}
|
||||||
|
.footer {{ text-align: center; color: #666; margin-top: 20px; font-size: 12px; }}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>Welcome to Brand Master!</h1>
|
||||||
|
<p>Your premium fashion destination</p>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>Hello {full_name},</p>
|
||||||
|
<p>Welcome aboard! Your account has been created successfully.</p>
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
<h3>What you can do:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>✅ Browse our collection of premium shoes and apparel</li>
|
||||||
|
<li>✅ Add items to your wishlist</li>
|
||||||
|
<li>✅ Place orders with secure checkout</li>
|
||||||
|
<li>✅ Track your order history</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<a href="https://brand-master.dvirlabs.com" class="button">Start Shopping</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p>Questions? Contact us at info@brandmaster.com</p>
|
||||||
|
<p>This is an automated message from Brand Master.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return send_email(email, subject, body, html_body)
|
||||||
109
quick-fix.bat
Normal file
109
quick-fix.bat
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
@echo off
|
||||||
|
REM Quick Fix Script - Apply Migrations and Deploy
|
||||||
|
REM This script fixes the database errors and deploys the updated system
|
||||||
|
|
||||||
|
echo ================================================================
|
||||||
|
echo Brand Master - Quick Fix Deployment
|
||||||
|
echo ================================================================
|
||||||
|
echo.
|
||||||
|
echo This will:
|
||||||
|
echo 1. Apply contact messages migration (fix full_name error)
|
||||||
|
echo 2. Apply flexible login migration (fix username error)
|
||||||
|
echo 3. Rebuild and deploy backend/frontend
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
|
||||||
|
REM Step 1: Apply Contact Messages Migration
|
||||||
|
echo ================================================================
|
||||||
|
echo Step 1: Applying contact messages migration...
|
||||||
|
echo ================================================================
|
||||||
|
call apply-migration.bat 007_enhance_contact_messages.sql
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] Failed to apply contact messages migration
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM Step 2: Apply Flexible Login Migration
|
||||||
|
echo ================================================================
|
||||||
|
echo Step 2: Applying flexible login migration...
|
||||||
|
echo ================================================================
|
||||||
|
call apply-migration.bat 008_add_username_to_users.sql
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] Failed to apply flexible login migration
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM Step 3: Build and Deploy
|
||||||
|
echo ================================================================
|
||||||
|
echo Step 3: Building and deploying...
|
||||||
|
echo ================================================================
|
||||||
|
|
||||||
|
set BACKEND_IMAGE=harbor.dvirlabs.com/my-apps/brand-master-backend:latest
|
||||||
|
set FRONTEND_IMAGE=harbor.dvirlabs.com/my-apps/brand-master-frontend:latest
|
||||||
|
|
||||||
|
echo Building backend...
|
||||||
|
cd backend
|
||||||
|
docker build -t %BACKEND_IMAGE% .
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] Backend build failed
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo Building frontend...
|
||||||
|
cd frontend
|
||||||
|
docker build -t %FRONTEND_IMAGE% .
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo [ERROR] Frontend build failed
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo Pushing images...
|
||||||
|
docker push %BACKEND_IMAGE%
|
||||||
|
docker push %FRONTEND_IMAGE%
|
||||||
|
|
||||||
|
echo Deploying to Kubernetes...
|
||||||
|
cd brand-master-chart
|
||||||
|
helm upgrade brand-master . --namespace my-apps --wait --timeout 5m
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ================================================================
|
||||||
|
echo Deployment Complete!
|
||||||
|
echo ================================================================
|
||||||
|
echo.
|
||||||
|
echo FIXED ISSUES:
|
||||||
|
echo ✅ Contact form "full_name" error - FIXED
|
||||||
|
echo ✅ Password reset "username" error - FIXED
|
||||||
|
echo ✅ Email sending functionality - ADDED
|
||||||
|
echo.
|
||||||
|
echo NEXT STEPS:
|
||||||
|
echo.
|
||||||
|
echo 1. CONFIGURE EMAIL (Required for password reset to work):
|
||||||
|
echo - Read EMAIL_SETUP.md for detailed instructions
|
||||||
|
echo - Quick setup: Update brand-master-chart/values.yaml with SMTP settings
|
||||||
|
echo - Or check backend logs for PIN (printed to console if email not configured)
|
||||||
|
echo.
|
||||||
|
echo 2. TEST PASSWORD RESET:
|
||||||
|
echo - Go to login page
|
||||||
|
echo - Click "Forgot Password"
|
||||||
|
echo - Enter your email
|
||||||
|
echo - Check email for PIN (or backend logs if email not configured)
|
||||||
|
echo - Enter PIN and new password
|
||||||
|
echo.
|
||||||
|
echo 3. VIEW BACKEND LOGS:
|
||||||
|
echo kubectl logs -n my-apps deployment/brand-master-backend -f
|
||||||
|
echo.
|
||||||
|
echo 4. CHECK EMAIL CONFIGURATION:
|
||||||
|
echo kubectl exec -n my-apps deployment/brand-master-backend -- env ^| findstr SMTP
|
||||||
|
echo.
|
||||||
|
echo FOR EMAIL SETUP HELP: See EMAIL_SETUP.md
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
Loading…
x
Reference in New Issue
Block a user