11 KiB
Database Overview - What Your Database is Doing
Database Purpose
Your PostgreSQL database is the central data store for a Farm Market Authentication Service that handles:
- User Authentication (Phone-based OTP login)
- Farm/Marketplace Data (Animals, Listings, Locations)
- Security & Audit Logging
- Session Management (Multi-device support)
Table Categories
🔐 AUTHENTICATION TABLES
1. users - User Accounts
Purpose: Store user account information Key Fields:
id(UUID) - Primary keyphone_number(UNIQUE) - Phone is the login identifiername- User's name (can be NULL until profile completed)user_type- Enum: 'seller', 'buyer', 'service_provider'role- System role: 'user', 'admin', 'moderator'token_version- Incremented on logout-all to invalidate all tokenslast_login_at- Tracks last login time
Current Usage:
- Created AFTER OTP verification (find-or-create pattern)
- Phone number is encrypted before storage
- One phone number = One account (UNIQUE constraint)
2. otp_codes - OTP Storage (ACTIVELY USED)
Purpose: Store OTP codes for phone verification Key Fields:
id(UUID)phone_number- Phone requesting OTP (NO user_id - user doesn't exist yet)otp_hash- Hashed OTP code (bcrypt)expires_at- OTP expiry (2 minutes default)attempt_count- Failed verification attemptscreated_at
Current Usage:
- Created when
/auth/request-otpis called - Deleted after successful verification or expiry
- Used for OTP verification in
/auth/verify-otp
3. otp_requests - Legacy OTP Table (NOT ACTIVELY USED)
Purpose: Alternative OTP storage (currently unused)
Note: Your code uses otp_codes table, not otp_requests
4. refresh_tokens - Session Management
Purpose: Store refresh tokens for JWT authentication Key Fields:
id(UUID)user_id- Links to users tabletoken_id(UNIQUE) - UUID identifier for tokentoken_hash- Hashed refresh token (bcrypt)device_id- Device identifier from clientexpires_at- Token expiryrevoked_at- NULL = active, timestamp = revokedrotated_from_id- Links to previous token (rotation tracking)reuse_detected_at- Detects token theft/reuse
Current Usage:
- Created during OTP verification
- Rotated on each refresh (old token revoked, new one created)
- Tracks which device each token belongs to
- Supports multi-device logins (one token per device)
5. user_devices - Device Tracking
Purpose: Track user's logged-in devices Key Fields:
id(UUID)user_id- Links to usersdevice_identifier- Unique device ID (e.g., Firebase Installation ID)device_platform- 'android', 'ios'device_model,os_version,app_versionfirst_seen_at,last_seen_atis_active- Whether device session is active- UNIQUE(
user_id,device_identifier) - One record per user-device pair
Current Usage:
- Created/updated during OTP verification
- Tracks all devices a user is logged in from
- Used for device management (view/revoke devices)
6. auth_audit - Security Audit Log
Purpose: Log all authentication events for security monitoring Key Fields:
id(UUID)user_id- NULL if user doesn't exist yet (e.g., failed login)action- 'otp_request', 'otp_verify', 'token_refresh', 'logout', etc.status- 'success', 'failed', 'error'ip_address,user_agent,device_idmeta(JSONB) - Additional metadata (errors, risk scores, etc.)created_at
Current Usage:
- Logs every authentication event
- Used by admin dashboard for security monitoring
- Used for risk scoring and anomaly detection
- Tracks suspicious activities (enumeration, brute force, etc.)
🏪 MARKETPLACE TABLES
7. species - Animal Species
Purpose: Master data for animal species (e.g., "Cow", "Goat", "Sheep") Key Fields:
id(UUID)name(UNIQUE)
8. breeds - Animal Breeds
Purpose: Breeds within each species (e.g., "Holstein", "Jersey" for Cow) Key Fields:
id(UUID)species_id- Links to speciesname- Breed name- UNIQUE(
species_id,name)
9. locations - Geographic Locations
Purpose: Store farm/home/office locations Key Fields:
id(UUID)user_id- Links to users (NULL = temporary/captured location)is_saved_address- Whether user saved this locationlocation_type- Enum: 'farm', 'home', 'office', etc.country,state,district,city_village,pincodelat,lng- GPS coordinatessource_type- 'device_gps', 'manual', 'unknown'source_confidence- 'high', 'medium', 'low'
Current Usage:
- Stores where animals are kept
- Stores listing locations
- Can be temporary (no user_id) or saved (with user_id)
10. animals - Animal Records
Purpose: Store individual animal information Key Fields:
id(UUID)species_id,breed_id- Animal classificationlocation_id- Where animal is keptsex- Enum: 'M', 'F', 'Neutered'age_months,weight_kgpurpose- Enum: 'dairy', 'meat', 'breeding', 'pet', 'work', 'other'health_status- Enum: 'healthy', 'minor_issues', 'serious_issues'vaccinated,dewormedmilk_yield_litre_per_day- For dairy animalsear_tag_no- Ear tag identificationquantity- Number of animals (default: 1)
Current Usage:
- Created by sellers when they want to list animals
- Linked to listings (one animal per listing)
11. listings - Marketplace Listings
Purpose: Animals for sale/stud service/adoption Key Fields:
id(UUID)seller_id- Links to users (who is selling)animal_id- Links to animals (what is being sold)title,price,currency(default: 'INR')listing_type- Enum: 'sale', 'stud_service', 'adoption'status- Enum: 'active', 'sold', 'expired', 'hidden'is_negotiable- Price negotiation allowed- Engagement metrics:
views_count,bookmarks_count,enquiries_call_count,enquiries_whatsapp_count,clicks_count
Current Usage:
- Created when seller lists an animal
- Tracked engagement metrics
- Can be marked as sold/expired/hidden
12. listing_images - Listing Photos
Purpose: Store images for listings Key Fields:
id(UUID)listing_id- Links to listingsimage_url- URL to imageis_primary- Main image flagsort_order- Image ordering
🔮 FUTURE TABLES
13. oauth_accounts - OAuth Integration (Placeholder)
Purpose: Future OAuth support (Google, Facebook, Apple) Key Fields:
id(UUID)user_id- Links to usersprovider- 'google', 'facebook', 'apple'provider_user_id- OAuth provider's user ID- UNIQUE(
provider,provider_user_id)
Current Usage:
- Table exists but not actively used yet
Key Relationships & Constraints
Foreign Key Relationships:
users (1) ──< (many) user_devices
users (1) ──< (many) refresh_tokens
users (1) ──< (many) listings
users (1) ──< (many) locations
listings (1) ──< (many) listing_images
listings (many) ──> (1) animals
animals (many) ──> (1) locations
animals (many) ──> (1) species
animals (many) ──> (1) breeds
breeds (many) ──> (1) species
Cascade Behaviors:
- DELETE user → Cascades delete to:
user_devices,refresh_tokens,listings,locations - DELETE species → RESTRICTED (can't delete if animals reference it)
- DELETE breed → Sets
breed_idto NULL on animals (SET NULL) - DELETE listing → Cascades delete to:
listing_images - DELETE animal → RESTRICTED (can't delete if listings reference it)
- DELETE location → RESTRICTED (can't delete if animals reference it)
Current Data Flow
Authentication Flow:
1. User requests OTP
└─> INSERT into `otp_codes` (phone_number, otp_hash, expires_at)
2. User verifies OTP
├─> Verify OTP from `otp_codes` table
├─> DELETE OTP from `otp_codes`
├─> FIND or CREATE user in `users` table
├─> INSERT/UPDATE `user_devices` table
├─> INSERT into `refresh_tokens` table
└─> INSERT into `auth_audit` (log event)
3. User refreshes token
├─> Verify refresh token from `refresh_tokens` table
├─> ROTATE token (revoke old, create new)
└─> INSERT into `auth_audit` (log event)
Marketplace Flow:
1. Seller creates listing
├─> CREATE `location` (where animal is)
├─> CREATE `animal` (animal details)
└─> CREATE `listing` (link animal to seller)
2. Buyer views listing
└─> UPDATE `listings.views_count`
3. Buyer bookmarks/contacts
└─> UPDATE engagement metrics (bookmarks_count, enquiries_*)
Database Features
1. Automatic Timestamps
- All tables have
created_atandupdated_at updated_atautomatically updated via database triggers
2. UUID Primary Keys
- All tables use UUIDs (not auto-increment integers)
- Generated via PostgreSQL
uuid-osspextension
3. Enum Types
- PostgreSQL ENUM types for controlled values:
sex_enum,purpose_enum,health_status_enumlocation_type_enum,listing_type_enum,listing_status_enumuser_type_enum,listing_role_enum
4. Indexes
- Indexes on foreign keys for fast joins
- Indexes on frequently queried fields (phone_number, expires_at, status)
- Partial indexes for performance (e.g., unconsumed OTPs)
5. Data Integrity
- CHECK constraints (e.g., non-negative counters)
- UNIQUE constraints (phone_number, user+device pairs)
- Foreign key constraints with appropriate CASCADE/RESTRICT behaviors
What's NOT in the Database (Handled Elsewhere)
- Access Tokens (JWT) - Stored only on client, validated via signature
- Rate Limiting Counters - Stored in Redis or in-memory (not PostgreSQL)
- OTP Codes (Plain) - Only hashed versions stored, plain codes never persisted
- SMS Messages - Sent via Twilio, not stored in database
- User Passwords - Phone-based auth only, no password storage
Current Issues / Design Notes
⚠️ Dual OTP Tables
otp_codes- ACTIVELY USED by your codeotp_requests- NOT USED (legacy/alternative table)- Recommendation: Consider removing
otp_requestsif not needed
⚠️ Phone Number Encryption
- Phone numbers in
usersandotp_codesare encrypted at application level - Database stores encrypted values, not plaintext
- Encryption handled by
src/utils/fieldEncryption.js
✅ Multi-Device Support
- Users can log in from multiple devices simultaneously
- Each device has its own refresh token
- Devices can be managed (viewed/revoked) via API
✅ Security Features
- OTP attempt tracking (prevents brute force)
- Token rotation (prevents token reuse)
- Audit logging (tracks all auth events)
- Risk scoring (detects suspicious activity)
Summary
Your database is a well-structured PostgreSQL database that:
- ✅ Handles phone-based authentication securely
- ✅ Supports a farm marketplace (animals, listings, locations)
- ✅ Tracks multi-device user sessions
- ✅ Logs security events for monitoring
- ✅ Uses proper constraints and relationships
- ✅ Supports data encryption at application level
The design follows good practices with UUIDs, enums, cascades, and proper indexing.