feat: Add client-side validation for admin creation and setup guide
Admin Creation Improvements: - Add comprehensive client-side validation before API call - Validate username (required, max 100 chars) - Validate email format - Validate password (min 8 chars for new admins) - Validate role selection - Better error messages for users - Trim and normalize input data Documentation: - Create comprehensive SETUP_GUIDE.md - Include feature checklist - Add testing checklist - Add troubleshooting section - Document API endpoints - Include database setup instructions This should resolve the 'validation failed' error by catching issues client-side before the API call.
This commit is contained in:
199
SETUP_GUIDE.md
Normal file
199
SETUP_GUIDE.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Setup Guide - Moyos Wedding App
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Database Setup
|
||||
|
||||
Run migrations and seed the database:
|
||||
|
||||
```bash
|
||||
# Generate Prisma client
|
||||
npx prisma generate
|
||||
|
||||
# Run migrations (applies schema changes)
|
||||
npx prisma migrate deploy
|
||||
# OR for development:
|
||||
npx prisma migrate dev
|
||||
|
||||
# Seed database (creates default admin and super admins)
|
||||
npm run db:seed
|
||||
```
|
||||
|
||||
### 2. Set Up Super Admins
|
||||
|
||||
The seed script will create two super admin accounts:
|
||||
- **Username**: `denverm` | **Email**: `deemoyo@gmail.com`
|
||||
- **Username**: `mahaliam` | **Email**: `mahalialerato@gmail.com`
|
||||
- **Default Password**: `TSD107AS#` (or set `DEFAULT_ADMIN_PASSWORD` env variable)
|
||||
|
||||
To manually set/update super admin passwords:
|
||||
|
||||
```bash
|
||||
# Set DEFAULT_ADMIN_PASSWORD environment variable (optional)
|
||||
export DEFAULT_ADMIN_PASSWORD="your-secure-password"
|
||||
|
||||
# Run the super admin setup script
|
||||
npx tsx scripts/set-super-admins.ts
|
||||
```
|
||||
|
||||
### 3. Environment Variables
|
||||
|
||||
Ensure these are set in your `.env` file:
|
||||
|
||||
```env
|
||||
# Database
|
||||
DATABASE_URL="postgresql://..."
|
||||
|
||||
# Supabase (for admin auth)
|
||||
NEXT_PUBLIC_SUPABASE_URL="..."
|
||||
SUPABASE_SERVICE_ROLE_KEY="..."
|
||||
|
||||
# Email (Resend)
|
||||
RESEND_API_KEY="..."
|
||||
FROM_EMAIL="noreply@themoyos.co.za"
|
||||
|
||||
# Optional: Default admin password
|
||||
DEFAULT_ADMIN_PASSWORD="TSD107AS#"
|
||||
```
|
||||
|
||||
### 4. Start the Application
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Feature Checklist
|
||||
|
||||
### ✅ Completed Features
|
||||
|
||||
1. **Edit Guestbook Messages**
|
||||
- ✅ Admin can edit any message
|
||||
- ✅ Guests can edit their own messages
|
||||
- ✅ "Edited" indicators displayed
|
||||
|
||||
2. **Edit Tributes**
|
||||
- ✅ Admin can edit any tribute
|
||||
- ✅ Guests can edit their own tributes
|
||||
- ✅ "Edited" indicators displayed
|
||||
|
||||
3. **Edit Relationship**
|
||||
- ✅ Admin can edit guest relationships from dashboard
|
||||
|
||||
4. **RSVP Email Notifications**
|
||||
- ✅ Admins receive email when guests submit RSVP
|
||||
- ✅ Email preferences toggle in admin settings
|
||||
- ✅ Configurable per admin
|
||||
|
||||
5. **Who's Who Feature**
|
||||
- ✅ Filter by relationship type
|
||||
- ✅ Filter by opt-in status
|
||||
- ✅ View all guests by category
|
||||
|
||||
6. **Reports & Exports**
|
||||
- ✅ Statistics dashboard (fixed)
|
||||
- ✅ CSV export (working)
|
||||
- ✅ Excel export (newly implemented)
|
||||
- ✅ PDF export (newly implemented)
|
||||
- ✅ All report types: Headcount, Dietary, Relationships, Seating
|
||||
|
||||
7. **Wedding Day Tools**
|
||||
- ✅ Guest check-in/undo check-in
|
||||
- ✅ QR code generation and printing
|
||||
- ✅ Attendance tracking
|
||||
- ✅ Emergency contacts management
|
||||
- ✅ Guest lookup and search
|
||||
- ✅ Check-in list export
|
||||
|
||||
8. **Activity Feed**
|
||||
- ✅ Real-time updates
|
||||
- ✅ Tracks RSVP, guestbook, tributes, profile updates
|
||||
- ✅ Shows edit indicators
|
||||
|
||||
9. **Admin Creation**
|
||||
- ✅ CSRF protection added
|
||||
- ✅ Client-side validation added
|
||||
- ✅ Proper error handling
|
||||
|
||||
10. **Super Admin Setup**
|
||||
- ✅ Migration created
|
||||
- ✅ Seed script updated
|
||||
- ✅ Setup script available
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Admin Features
|
||||
- [ ] Login as super admin
|
||||
- [ ] Create new admin user (test validation)
|
||||
- [ ] Edit guestbook message
|
||||
- [ ] Edit tribute
|
||||
- [ ] Edit guest relationship
|
||||
- [ ] Toggle RSVP email notifications
|
||||
- [ ] Filter Who's Who by relationship/opt-in
|
||||
- [ ] Export reports (CSV, Excel, PDF)
|
||||
- [ ] Use Wedding Day Tools (check-in, QR codes)
|
||||
- [ ] View Activity Feed
|
||||
|
||||
### Guest Features
|
||||
- [ ] Login as guest
|
||||
- [ ] Edit own guestbook message
|
||||
- [ ] Edit own tribute
|
||||
- [ ] Submit RSVP (verify admin receives email)
|
||||
- [ ] View Who's Who directory
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Admin Creation Fails
|
||||
- Check CSRF token is being sent
|
||||
- Verify Supabase is configured
|
||||
- Check validation errors in browser console
|
||||
- Ensure password is at least 8 characters
|
||||
|
||||
### Super Admins Not Created
|
||||
- Run `npx tsx scripts/set-super-admins.ts`
|
||||
- Check database connection
|
||||
- Verify `DEFAULT_ADMIN_PASSWORD` is set if using custom password
|
||||
|
||||
### Reports Not Exporting
|
||||
- Check browser console for errors
|
||||
- Verify admin session is valid
|
||||
- For Excel: Check server logs for exceljs errors
|
||||
- For PDF: Ensure jsPDF is loaded in browser
|
||||
|
||||
### Email Notifications Not Sending
|
||||
- Verify `RESEND_API_KEY` is set
|
||||
- Check `FROM_EMAIL` is configured
|
||||
- Verify admin has `receiveRsvpNotifications: true`
|
||||
- Check email logs in admin dashboard
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Guest Endpoints
|
||||
- `PUT /api/guestbook/[id]` - Edit own guestbook message
|
||||
- `PUT /api/tribute/[id]` - Edit own tribute
|
||||
|
||||
### Admin Endpoints
|
||||
- `PUT /api/admin/tributes/[id]` - Edit any tribute
|
||||
- `PUT /api/admin/guests/[id]/relationship` - Edit guest relationship
|
||||
- `GET/PUT /api/admin/settings/email-preferences` - Email preferences
|
||||
- `GET /api/admin/reports/summary` - Report statistics
|
||||
- `GET /api/admin/reports/export?type=X&format=Y` - Export reports
|
||||
- `GET /api/admin/whos-who` - Who's Who with filters
|
||||
- `GET /api/admin/activity-log` - Activity feed
|
||||
- `POST /api/admin/guests/[id]/check-in` - Check in guest
|
||||
- `DELETE /api/admin/guests/[id]/check-in` - Undo check-in
|
||||
|
||||
## Database Schema Updates
|
||||
|
||||
The following fields were added to the `Admin` model:
|
||||
- `receiveRsvpNotifications` (Boolean, default: true)
|
||||
- `role` (String, default: "viewer")
|
||||
|
||||
Migration file: `prisma/migrations/20260123000000_add_admin_email_preferences_and_role/migration.sql`
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Run database migrations
|
||||
2. Seed the database
|
||||
3. Set up super admins
|
||||
4. Test all features
|
||||
5. Deploy to production
|
||||
@@ -103,30 +103,82 @@ export function RBACManager() {
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
// Client-side validation
|
||||
if (!newUser.username || newUser.username.trim().length === 0) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "Username is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (newUser.username.length > 100) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "Username must be 100 characters or less",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newUser.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(newUser.email)) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "A valid email address is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newUser.role || !['viewer', 'moderator', 'super_admin'].includes(newUser.role)) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "A valid role must be selected",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const url = editingUser
|
||||
? `/api/admin/roles/${editingUser.id}`
|
||||
: "/api/admin/roles";
|
||||
const method = editingUser ? "PUT" : "POST";
|
||||
|
||||
const password = (newUser.password || "").toString();
|
||||
if (method === "POST") {
|
||||
if (!password || password.length < 8) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "Password is required and must be at least 8 characters",
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (password && password.length > 0 && password.length < 8) {
|
||||
toast({
|
||||
variant: "error",
|
||||
title: "Validation Error",
|
||||
description: "Password must be at least 8 characters if provided",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const csrfToken = await getCSRFToken();
|
||||
if (!csrfToken) {
|
||||
throw new Error("Authentication required (missing CSRF token). Please refresh and try again.");
|
||||
}
|
||||
|
||||
const payload: Record<string, unknown> = {
|
||||
username: newUser.username,
|
||||
email: newUser.email,
|
||||
username: newUser.username.trim(),
|
||||
email: newUser.email.trim().toLowerCase(),
|
||||
role: newUser.role,
|
||||
};
|
||||
|
||||
const password = (newUser.password || "").toString();
|
||||
if (method === "POST") {
|
||||
if (!password) {
|
||||
throw new Error("Password is required to create a new admin.");
|
||||
}
|
||||
payload.password = password;
|
||||
} else if (password) {
|
||||
// Optional password reset on edit
|
||||
} else if (password && password.length >= 8) {
|
||||
// Optional password reset on edit (only if valid)
|
||||
payload.password = password;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user