Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

4 Commits

Folders and files

Repository files navigation

Restricted Registered Emails System

A comprehensive security solution for preventing registration with privileged, reserved, or system-critical email addresses. Includes backend API, PostgreSQL database, admin management UI, and integration examples for your registration endpoint.

πŸ”’ Security Features

  • Three Matching Types: Exact match (localpart), domain-level blocking, and regex patterns
  • Multi-Domain Support: Apply global rules or domain-specific restrictions
  • Audit Trail: Complete logging of all blocklist changes with timestamps and user attribution
  • Flexible Management: Add/edit/delete entries, bulk import/export (CSV)
  • Pre-Populated Defaults: Includes common reserved addresses (admin, support, noreply, etc.)

πŸ“‹ Table of Contents

πŸš€ Quick Start

Prerequisites

  • Node.js 18+
  • PostgreSQL 12+
  • npm or yarn

Backend Setup

cd backend
npm install
cp .env.example .env
# Edit .env with your database credentials
npm run db:migrate
npm run dev

Frontend Setup

cd frontend
npm install
npm run dev

Visit http://localhost:3001 to access the admin dashboard.

πŸ—οΈ Architecture

Backend Stack

  • Runtime: Node.js with Express.js
  • Language: TypeScript
  • Database: PostgreSQL with audit triggers
  • API: RESTful API with JSON responses

Frontend Stack

  • Framework: React 18 with TypeScript
  • Build Tool: Vite
  • Styling: Tailwind CSS
  • UI Components: Custom with Lucide icons

Database Schema

restricted_emails
β”œβ”€β”€ id (UUID, PK)
β”œβ”€β”€ pattern (VARCHAR, the email pattern)
β”œβ”€β”€ type (VARCHAR: 'exact' | 'domain' | 'regex')
β”œβ”€β”€ applicable_domains (TEXT[], NULL for all domains)
β”œβ”€β”€ reason (TEXT, optional)
β”œβ”€β”€ created_by (VARCHAR)
β”œβ”€β”€ created_at (TIMESTAMP)
β”œβ”€β”€ updated_at (TIMESTAMP)
β”œβ”€β”€ is_active (BOOLEAN)
└── ...

restricted_emails_audit
β”œβ”€β”€ id (UUID, PK)
β”œβ”€β”€ restricted_email_id (UUID, FK)
β”œβ”€β”€ action (VARCHAR: 'CREATE' | 'UPDATE' | 'DELETE')
β”œβ”€β”€ pattern_before / pattern_after
β”œβ”€β”€ type_before / type_after
β”œβ”€β”€ domains_before / domains_after
β”œβ”€β”€ reason_before / reason_after
β”œβ”€β”€ changed_by (VARCHAR)
β”œβ”€β”€ change_timestamp (TIMESTAMP)
└── ...

πŸ“¦ Installation

1. Clone or Extract Files

cd /path/to/Restricted-Registered-Emails

2. Set Up Backend

cd backend
npm install
cp .env.example .env

Edit .env with your PostgreSQL credentials:

DATABASE_URL=postgresql://postgres:password@localhost:5432/restricted_emails_db
DB_HOST=localhost
DB_PORT=5432
DB_NAME=restricted_emails_db
DB_USER=postgres
DB_PASSWORD=yourpassword
PORT=3000
NODE_ENV=development
CORS_ORIGIN=http://localhost:3001

3. Initialize Database

npm run db:migrate

This will create all tables, indexes, triggers, and seed default restricted emails.

4. Start Backend Server

npm run dev

Server will start on http://localhost:3000

5. Set Up Frontend

cd ../frontend
npm install
npm run dev

Access the admin dashboard at http://localhost:3001

βš™οΈ Configuration

Environment Variables (Backend)

Variable Description Default
DATABASE_URL PostgreSQL connection string -
DB_HOST Database host localhost
DB_PORT Database port 5432
DB_NAME Database name restricted_emails_db
DB_USER Database user postgres
DB_PASSWORD Database password postgres
PORT Server port 3000
NODE_ENV Environment development
CORS_ORIGIN CORS allowed origin http://localhost:3001
JWT_SECRET (Optional) JWT secret for auth your-secret-key

Frontend Configuration

Edit frontend/vite.config.ts to change the API proxy target:

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:3000',  // Change to your backend URL
      changeOrigin: true,
    },
  },
},

πŸ“š API Documentation

Base URL

http://localhost:3000/api/blocklist

Endpoints

1. Get All Restricted Emails

GET /api/blocklist?page=1&pageSize=20&search=admin&type=exact&domain=example.com

Query Parameters:

  • page (integer, default: 1) - Page number
  • pageSize (integer, default: 20) - Entries per page
  • search (string) - Search by pattern
  • type (string) - Filter by type (exact, domain, regex)
  • domain (string) - Filter by applicable domain

Response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "pattern": "admin",
      "type": "exact",
      "applicableDomains": null,
      "reason": "Reserved for admin accounts",
      "createdBy": "system",
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T10:30:00Z",
      "isActive": true
    }
  ],
  "total": 150,
  "page": 1,
  "pageSize": 20,
  "totalPages": 8
}

2. Get Single Entry

GET /api/blocklist/{id}

3. Create Restricted Email

POST /api/blocklist
Content-Type: application/json

{
  "pattern": "admin",
  "type": "exact",
  "applicableDomains": null,
  "reason": "Reserved for administrative accounts"
}

Response: 201 Created with created entry

4. Update Entry

PUT /api/blocklist/{id}
Content-Type: application/json

{
  "reason": "Updated reason"
}

5. Delete Entry

DELETE /api/blocklist/{id}

Response: 204 No Content (soft delete - marks as inactive)

6. Validate Email

POST /api/blocklist/validate
Content-Type: application/json

{
  "email": "admin@example.com",
  "domain": "example.com"
}

Response:

{
  "isBlocked": true,
  "blockedPattern": {
    "id": "...",
    "pattern": "admin",
    "type": "exact",
    "reason": "Reserved for admin accounts"
  },
  "reason": "This email address is reserved for system use."
}

7. Bulk Import

POST /api/blocklist/bulk-import
Content-Type: application/json

{
  "csvContent": "pattern,type,applicable_domains,reason\nadmin,exact,,Admin account\nsupport,exact,,Support team",
  "createdBy": "admin"
}

CSV Format:

pattern,type,applicable_domains,reason
admin,exact,,Reserved for admin accounts
support,exact,,Reserved for support team
noreply,exact,,Reserved for system notifications
security,exact,,Reserved for security team
help,exact,,Reserved for help desk

Response:

{
  "success": true,
  "inserted": 5,
  "errors": [],
  "data": [...]
}

8. Export Blocklist

GET /api/blocklist/export

Response: CSV file download

9. Get Audit Log (for entry)

GET /api/blocklist/{id}/audit?page=1&pageSize=20

10. Get Global Audit Log

GET /api/blocklist/audit/all?page=1&pageSize=20&action=CREATE

πŸ–₯️ Admin Dashboard

The React dashboard provides a user-friendly interface for managing the blocklist.

Features

  1. View Blocklist

    • Paginated table with sorting
    • Search by pattern
    • Filter by type (exact, domain, regex)
    • Filter by applicable domain
  2. Add Entry

    • Pattern input
    • Match type selector
    • Domain picker (multi-select or global)
    • Reason/notes field
  3. Edit Entry

    • Inline editing modal
    • Update any field
    • Automatic audit logging
  4. Delete Entry

    • Soft delete with confirmation
    • Preserves history in audit log
  5. Bulk Operations

    • CSV import with preview
    • Drag-and-drop file upload
    • CSV export with templates
    • Error reporting for failed imports
  6. Audit Log View

    • Track all changes
    • View who changed what and when
    • Filter by action type

πŸ”— Integration Guide

How to Integrate with Your Registration Endpoint

See backend/src/routes/register-example.ts for a complete example.

Step 1: Import the Service

import { EmailBlocklistService } from '../services/emailBlocklist';
import { getPool } from '../database/connection';

const blocklistService = new EmailBlocklistService(getPool());

Step 2: Check Email in Registration Handler

app.post('/api/register', async (req, res) => {
  const { email, password, domain } = req.body;

  // Validate email format
  if (!isValidEmailFormat(email)) {
    return res.status(400).json({ error: 'Invalid email format' });
  }

  // βœ“ KEY STEP: Check if email is blocked
  const blockCheck = await blocklistService.isEmailBlocked(email, domain);
  if (blockCheck.isBlocked) {
    return res.status(403).json({
      error: blockCheck.reason || 'This email address cannot be used for registration',
      code: 'EMAIL_RESTRICTED',
    });
  }

  // Check if already registered
  const existing = await findUserByEmail(email);
  if (existing) {
    return res.status(409).json({ error: 'Email already registered' });
  }

  // Create user account
  const user = await createUser({ email, password });
  
  res.status(201).json({ userId: user.id });
});

Step 3: (Optional) Real-Time Validation Endpoint

app.post('/api/validate-email', async (req, res) => {
  const { email, domain } = req.body;

  const isBlocked = await blocklistService.isEmailBlocked(email, domain);
  const isRegistered = await checkUserExists(email);

  res.json({
    isValid: !isBlocked.isBlocked && !isRegistered,
    isBlocked: isBlocked.isBlocked,
    message: isBlocked.reason,
  });
});

Integration Points

  • Email Validation: Before creating user account in registration/signup endpoint
  • API Endpoints: Make requests to POST /api/blocklist/validate
  • Frontend: Show validation errors in signup form
  • Logging: Log blocked attempts for security monitoring

πŸ§ͺ Testing

Run Unit Tests

cd backend
npm test

Run Specific Test File

npm test -- emailBlocklist.test.ts

Test Coverage

npm test -- --coverage

What's Tested

  • βœ… Exact match email validation
  • βœ… Domain-level blocking
  • βœ… Regex pattern matching
  • βœ… Case-insensitive matching
  • βœ… Whitespace trimming
  • βœ… Domain-specific restrictions
  • βœ… Invalid regex handling
  • βœ… Edge cases (multiple @, missing @, etc.)

🚒 Deployment

Production Checklist

  • Update .env with production database credentials
  • Set NODE_ENV=production
  • Enable HTTPS/SSL
  • Configure CORS for production domain
  • Set up database backups
  • Configure logging and monitoring
  • Rate limit registration endpoint
  • Set up audit log retention policy
  • Deploy backend and frontend separately
  • Test integration with your registration endpoint

Docker Deployment (Optional)

Create backend/Dockerfile:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

Build and run:

docker build -t restricted-emails-api .
docker run -p 3000:3000 -e DATABASE_URL=... restricted-emails-api

Environment-Specific Configs

Development:

NODE_ENV=development
CORS_ORIGIN=http://localhost:3001

Production:

NODE_ENV=production
CORS_ORIGIN=https://yourdomain.com
DATABASE_URL=postgresql://prod_user:secure_password@prod-db-host:5432/restricted_emails_db

πŸ“Š Matching Types Explained

1. Exact Match

Matches the local part of the email exactly (case-insensitive).

Examples:

  • Pattern: admin β†’ Blocks: admin@any.com, ADMIN@example.com
  • Pattern: support β†’ Blocks: support@example.com, support@other.io

2. Domain Match

Matches specific domain(s).

Examples:

  • Pattern: example.com β†’ Blocks: anyone@example.com, user@sub.example.com
  • Pattern: @domain.com β†’ Blocks: any@domain.com

3. Regex Pattern

Uses regular expressions for complex matching rules.

Examples:

  • Pattern: ^noreply-.*@example\.com$ β†’ Blocks: noreply-system@example.com, noreply-alerts@example.com
  • Pattern: admin.*@(example|test)\.com β†’ Blocks: admin.main@example.com, adminuser@test.com, etc.

πŸ” Common Use Cases

1. Block All Noreply Variations Across All Domains

Pattern: noreply | Type: Exact | Domains: None (global)

2. Block Specific Domain

Pattern: suspicious-domain.com | Type: Domain | Domains: None

3. Block Admin Accounts Only for One Domain

Pattern: admin | Type: Exact | Domains: example.com

4. Block Regex Patterns for Multiple Domains

Pattern: ^(noreply|mailer|daemon)-.* | Type: Regex | Domains: domain1.com, domain2.com

πŸ“ Default Blocklist

Out-of-the-box, these addresses are blocked globally:

  • admin, administrator - Administrative accounts
  • support, help - Support teams
  • noreply, no-reply - Notification systems
  • security, abuse - Security/abuse reporting
  • contact, info - Generic addresses
  • sales - Sales team
  • root, postmaster, mailer-daemon - System accounts

Edit or delete these from the admin dashboard as needed.

πŸ†˜ Troubleshooting

Database Connection Error

Error: connect ECONNREFUSED 127.0.0.1:5432

Solution: Ensure PostgreSQL is running. Check DB_HOST, DB_PORT, DB_USER, DB_PASSWORD in .env.

API Returns 403 for All Registrations

Solution: Check the audit log to see which pattern is blocking. The blocklist may be too strict. Adjust domain restrictions if needed.

Regex Pattern Not Matching

Solution: Test your regex in a tool like regex101.com. Remember patterns are case-insensitive by default.

CORS Errors in Frontend

Solution: Update CORS_ORIGIN in .env to match your frontend URL.

πŸ“„ License

MIT

Support

For issues, questions, or feature requests, please refer to the integration documentation or contact your security team.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages