Fix product filters and add admin password reset feature
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

- Fix: Product filters now properly send only non-empty values to backend
- Fix: Brand/gender/model filters now work correctly
- Add: FORCE_ADMIN_PASSWORD_RESET flag for resetting admin password on deployment
- Add: ADMIN_PASSWORD_RESET.md guide with instructions
- Update: Admin password reset logic with clear console messages
This commit is contained in:
dvirlabs 2026-05-11 08:04:19 +03:00
parent b68ab81a53
commit ad96ec33e6
5 changed files with 87 additions and 17 deletions

51
ADMIN_PASSWORD_RESET.md Normal file
View File

@ -0,0 +1,51 @@
# Admin Password Reset Guide
## How to Reset Admin Password
If you've changed your admin password and forgotten it, you can reset it using one of these methods:
### Method 1: Force Reset on Deployment (Recommended)
1. Edit the Helm values file: `~/OneDrive/Desktop/gitea/my-apps/charts/brand-master-chart/values.yaml`
2. Set the following environment variables:
```yaml
ADMIN_PASSWORD: "your-new-password"
FORCE_ADMIN_PASSWORD_RESET: "true"
```
3. Deploy the changes:
```bash
cd ~/OneDrive/Desktop/gitea/my-apps/charts
helm upgrade brand-master ./brand-master-chart -n my-apps
```
4. Wait for the backend pod to restart
5. **Important**: After logging in successfully, change `FORCE_ADMIN_PASSWORD_RESET` back to `"false"` and redeploy to prevent password reset on every startup
### Method 2: Use Password Reset Flow (If Email is Configured)
1. Go to the login page: https://brand-master.dvirlabs.com/login
2. Click "Forgot Password"
3. Enter your admin email address
4. Check your email for the PIN code
5. Enter the PIN and your new password
6. Login with the new password
### Method 3: Change Password from Profile (If Logged In)
1. Login to the admin account
2. Go to Profile page
3. Scroll to "Change Password" section
4. Enter old password and new password
5. Submit
## Current Admin Credentials
Check your deployment values file or pod logs for current credentials:
```bash
kubectl logs -n my-apps deployment/brand-master-backend | grep -A 3 "Admin"
```
## Notes
- The `FORCE_ADMIN_PASSWORD_RESET` flag is set to `"false"` by default for security
- Only set it to `"true"` when you need to reset the password
- Always change it back to `"false"` after resetting to prevent security issues

View File

@ -14,6 +14,7 @@ class Settings(BaseSettings):
admin_email: str = "admin@brandmaster.com"
admin_password: str = "Admin123!" # Change via ADMIN_PASSWORD env var
admin_full_name: str = "System Administrator"
force_admin_password_reset: bool = False # Set to True to reset admin password on every startup
# Email configuration for password reset
smtp_host: str = "smtp.gmail.com"

View File

@ -46,15 +46,19 @@ def create_admin_user():
admin = db.query(User).filter(User.email == settings.admin_email).first()
if admin:
# Admin exists, update password and details
# Admin exists - update password if force reset is enabled
if settings.force_admin_password_reset:
admin.hashed_password = get_password_hash(settings.admin_password)
admin.full_name = settings.admin_full_name
admin.is_active = True
admin.is_admin = True
db.commit()
print(f"✅ Admin user updated: {settings.admin_email}")
print(f"🔄 Admin password RESET (force_admin_password_reset=True): {settings.admin_email}")
print(f"📧 Email: {settings.admin_email}")
print(f"🔐 Password: {settings.admin_password}")
print(f"🔐 New Password: {settings.admin_password}")
else:
print(f" Admin user exists: {settings.admin_email} (password unchanged)")
print(f"💡 To reset password, set FORCE_ADMIN_PASSWORD_RESET=true and redeploy")
else:
# Create new admin user
admin = User(

View File

@ -32,6 +32,8 @@ backend:
ADMIN_EMAIL: "admin@brand-master.com"
ADMIN_PASSWORD: "admin123" # CHANGE THIS!
ADMIN_FULL_NAME: "System Administrator"
# Set to "true" to reset admin password on every deployment (useful if you forgot password)
FORCE_ADMIN_PASSWORD_RESET: "false"
# Email configuration for password reset (optional)
SMTP_HOST: "smtp.gmail.com"
SMTP_PORT: "587"

View File

@ -20,7 +20,7 @@ export default function Products() {
try {
setLoading(true)
const categorySlug = searchParams.get('category')
const params = { limit: 50, ...activeFilters }
const params = { limit: 50 }
if (categorySlug) {
// Get category by slug
@ -29,13 +29,25 @@ export default function Products() {
if (category) params.category_id = category.id
}
// Convert filter values to API parameters
if (activeFilters.gender) params.gender = activeFilters.gender
if (activeFilters.brand) params.brand = activeFilters.brand
if (activeFilters.min_price) params.min_price = parseFloat(activeFilters.min_price)
if (activeFilters.max_price) params.max_price = parseFloat(activeFilters.max_price)
if (activeFilters.onSale) params.on_sale = true
if (activeFilters.model_id) params.model_id = parseInt(activeFilters.model_id)
// Only add non-empty filter values to params
if (activeFilters.gender && activeFilters.gender !== '') {
params.gender = activeFilters.gender
}
if (activeFilters.brand && activeFilters.brand !== '') {
params.brand = activeFilters.brand
}
if (activeFilters.model_id && activeFilters.model_id !== '') {
params.model_id = parseInt(activeFilters.model_id)
}
if (activeFilters.min_price && activeFilters.min_price !== '') {
params.min_price = parseFloat(activeFilters.min_price)
}
if (activeFilters.max_price && activeFilters.max_price !== '') {
params.max_price = parseFloat(activeFilters.max_price)
}
if (activeFilters.onSale === true) {
params.on_sale = true
}
// Map sortBy to backend parameter
if (sortBy === 'price-low') {