# Security & Demo Mode

This guide covers security best practices and Demo Mode configuration.

# Demo Mode Overview

Demo Mode is a security feature that blocks all mutation operations (create, update, delete) while allowing read-only access.

# When to Use Demo Mode

  • Public demos: Show system without allowing changes
  • Testing environments: Prevent accidental data changes
  • Client previews: Let clients explore without modifying data

# When NOT to Use Demo Mode

  • Production: Should always be false in production
  • Development: Usually disabled for development

# Enabling/Disabling Demo Mode

# Method 1: Environment Variable

Edit .env file:

# Enable demo mode
DEMO_MODE=true

# Disable demo mode (production)
DEMO_MODE=false

Restart server after changing:

# Development
# Stop server (Ctrl+C) and restart

# Production
pm2 restart cloudpos

# Method 2: Admin Panel (If Available)

  1. Admin Panel → SettingsSecurity
  2. Toggle Demo Mode
  3. Save changes

# What Demo Mode Blocks

# Blocked Operations

Demo Mode blocks all mutation operations:

  • POST requests (create)
  • PUT requests (update)
  • PATCH requests (partial update)
  • DELETE requests (delete)
  • GET requests to mutation endpoints:
    • /toggle
    • /sync
    • /assign
    • /approve
    • /activate
    • /deactivate
    • /complete
    • /cancel

# Allowed Operations

Demo Mode allows read-only operations:

  • GET requests (view data)
  • Login/Register (auth endpoints)
  • View subscriptions (read-only)
  • View plans (read-only)
  • Public CMS pages (read-only)

# Error Message

When an operation is blocked, users see:

Demo mode enabled. Changes are disabled.

This appears as:

  • Toast notification (warning style)
  • 403 Forbidden HTTP status
  • Error code: DEMO_MODE

# Security Best Practices

# 1. Environment Variables

Never commit .env to Git:

  • Already in .gitignore
  • Use .env.example as template

Use strong secrets:

# Generate JWT secret
openssl rand -base64 32

# Generate encryption key
openssl rand -base64 32

Restrict file permissions:

chmod 600 .env

# 2. Database Security

Use dedicated database user:

CREATE USER 'cloudpos'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON cloudpos.* TO 'cloudpos'@'localhost';
FLUSH PRIVILEGES;

Don't use root user in production.

Regular backups:

# Daily backup
mysqldump -u cloudpos -p cloudpos > backup_$(date +%Y%m%d).sql

# 3. SSL/HTTPS

Always use HTTPS in production:

  • Required for secure authentication
  • Required for Stripe webhooks
  • Use Let's Encrypt (free SSL)

Configure Nginx:

server {
    listen 443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    # ... rest of config
}

# 4. Password Security

Strong password requirements:

  • Minimum 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one number

Change default passwords:

  • Admin: admin@cloudpos.com / admin123Change immediately
  • Test users: admin@acme.com / password123Change in production

Password hashing:

  • Passwords are hashed with bcrypt (automatic)
  • Never store plain text passwords

# 5. JWT Tokens

Use strong secrets:

  • Minimum 32 characters
  • Generate with: openssl rand -base64 32
  • Different secrets for access and refresh tokens

Token expiry:

  • Access tokens: 15 minutes (short-lived)
  • Refresh tokens: 7 days (longer-lived)

Token storage:

  • Stored in localStorage or sessionStorage
  • Automatically refreshed before expiry

# 6. CORS Configuration

Restrict CORS origins:

# Development
CORS_ORIGIN=http://localhost:5173

# Production (single domain)
CORS_ORIGIN=https://yourdomain.com

# Production (multiple domains)
# Configure in server code if needed

Never use: CORS_ORIGIN=* in production

# 7. Rate Limiting

CloudPOS includes rate limiting to prevent abuse:

  • API endpoints: Limited requests per minute
  • Authentication: Stricter limits on login/register
  • Automatic: Enabled by default

# 8. Input Validation

All API endpoints use:

  • Validation pipes: Automatic DTO validation
  • Type checking: TypeScript types
  • SQL injection protection: Prisma ORM (parameterized queries)
  • XSS protection: Input sanitization

# 9. File Upload Security

Restrict file types:

  • Only allow specific file types (images, PDFs)
  • Validate file extensions
  • Check MIME types

Limit file size:

# Nginx config
client_max_body_size 10M;

Store uploads securely:

  • Outside web root (if possible)
  • Restrict access permissions
  • Scan for malware (optional)

# 10. Admin Panel Security

Limit admin access:

  • Only create admin users when needed
  • Use role-based permissions
  • Audit admin actions (if audit logging enabled)

Strong admin passwords:

  • Use password manager
  • Enable 2FA if available
  • Rotate passwords periodically

# Security Checklist

# Pre-Launch Security

  • [ ] Change all default passwords
  • [ ] Generate strong JWT secrets
  • [ ] Generate strong encryption key
  • [ ] Use dedicated database user (not root)
  • [ ] Enable HTTPS/SSL
  • [ ] Configure CORS properly
  • [ ] Set DEMO_MODE=false in production
  • [ ] Restrict file permissions (.env, uploads)
  • [ ] Enable firewall (only allow 80, 443, 22)
  • [ ] Set up regular database backups
  • [ ] Monitor error logs
  • [ ] Review admin user access

# Ongoing Security

  • [ ] Keep dependencies updated
  • [ ] Monitor security advisories
  • [ ] Review access logs regularly
  • [ ] Rotate secrets periodically (90 days)
  • [ ] Test backups regularly
  • [ ] Update SSL certificates (auto-renewal)
  • [ ] Review and remove unused admin users

# Troubleshooting

# Demo Mode Not Working

Issue: Changes still allowed when DEMO_MODE=true

Solutions:

  1. Verify environment variable:

    # Check .env file
    cat .env | grep DEMO_MODE
    
  2. Restart server:

    # Development: Stop and restart
    # Production: pm2 restart cloudpos
    
  3. Check server logs:

    pm2 logs cloudpos | grep -i demo
    

# Can't Disable Demo Mode

Issue: Demo mode stays enabled

Solutions:

  1. Check .env file:

    • Must be DEMO_MODE=false (not False, FALSE, or 0)
    • No quotes around value
  2. Clear environment cache:

    • Restart server completely
    • Clear PM2 cache: pm2 delete cloudpos && pm2 start ecosystem.config.js

# Security Warnings

Issue: Browser shows security warnings

Solutions:

  1. Mixed content (HTTP/HTTPS):

    • Ensure all resources use HTTPS
    • Check API calls use HTTPS
    • Update VITE_API_URL to use HTTPS
  2. Invalid SSL certificate:

    • Renew SSL certificate
    • Check certificate expiry
    • Verify domain matches certificate

Next: See Troubleshooting for common issues and solutions.