PIN Lists Module Documentation
Table of Contents
- Module Overview (Technical)
- Module Overview (Commercial/Business)
- Module Overview (End User/Administrator)
- Configuration Fields Reference
- Call Flow / Logic Explanation
- Import/Export Feature
- Common Scenarios & Examples
- Limitations & Important Notes
- Troubleshooting Tips
- Glossary
---
1. Module Overview (Technical)
What Are PIN Lists?
PIN Lists provide authorization codes for controlled access to specific telephony features. Users must enter a valid PIN from the list to proceed with protected actions like international calls, DISA access, or restricted routes.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ PIN List Validation System │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Feature requests PIN validation (e.g., international call) │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Dialplan sets pin_list variable │ │
│ │ session:setVariable("pin_list", "international") │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ validate_pin.lua │ │
│ │ │ │
│ │ 1. Look up PIN list by name and domain │ │
│ │ SELECT id FROM public.pin_lists │ │
│ │ WHERE name = 'international' AND enabled = TRUE │ │
│ │ │ │
│ │ 2. Prompt user: "Enter your access PIN" │ │
│ │ │ │
│ │ 3. Validate entered PIN against members │ │
│ │ SELECT 1 FROM public.pin_list_members │ │
│ │ WHERE pin = [input] AND enabled = TRUE │ │
│ │ │ │
│ │ 4. Set result variable │ │
│ │ session:setVariable("pin_list_valid", "true/false") │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Dialplan continues or blocks based on pin_list_valid │
│ │
└─────────────────────────────────────────────────────────────────┘
Key Tables
| Table | Purpose |
|---|
public.pin_lists | PIN list definitions (name, enabled) | |
public.pin_list_members | Individual PINs within each list |
Key Files
| File | Description |
|---|
admin/apps/web/src/modules/pinLists/ | Frontend module | |
admin/apps/web/src/i18n/en/pinLists.json | English translations | |
telephony/freeswitch/lua/main/xml_handlers/pin/validate_pin.lua | PIN validation handler |
---
2. Module Overview (Commercial/Business)
Business Value
PIN Lists enable controlled access to premium or restricted features:
| Without PIN Lists | With PIN Lists |
|---|
| All users can dial international | Only authorized users | |
| No accountability | Track who used which PIN | |
| No cost control | Limit expensive calls | |
| No department segregation | Department-specific access |
Use Cases
- International Dialing Authorization
- Only managers can dial international
- PIN required before outbound connects
- DISA Security Layer
- Additional PIN after DISA authentication
- Two-factor for extra security
- Toll-Free Bypass
- Require PIN for toll-free abuse prevention
- Track usage by PIN
- Department Budgets
- Different PIN lists per department
- Track call costs by department
Feature Highlights
| Feature | Benefit |
|---|
| Multiple PINs per List | Share list with many users | |
| PIN Descriptions | Track who owns each PIN | |
| Enable/Disable | Temporarily revoke access | |
| Import/Export | Bulk management via CSV | |
| Multi-tenant | Separate lists per domain |
---
3. Module Overview (End User/Administrator)
What Can You Do?
- Create PIN lists for different purposes
- Add multiple PINs to each list
- Enable/disable individual PINs
- Import/export PINs via CSV
- Search and filter PINs
Administrator Workflow
┌─────────────────────────────────────────────────────────────────┐
│ Creating a PIN List │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Step 1: General Information │
│ ├─ List Name: "International Access" │
│ ├─ Description: "PINs for international dialing" │
│ └─ Enabled: ✓ │
│ │
│ Step 2: Add PINs │
│ ├─ PIN: 1234 | Description: "John Smith" | Enabled: ✓ │
│ ├─ PIN: 5678 | Description: "Jane Doe" | Enabled: ✓ │
│ ├─ PIN: 9012 | Description: "Sales Team" | Enabled: ✓ │
│ └─ PIN: 3456 | Description: "Guest Access" | Enabled: ✗ │
│ │
│ Step 3: Save │
│ │
│ Result: Users entering 1234, 5678, or 9012 pass validation │
│ User entering 3456 fails (disabled) │
│ │
└─────────────────────────────────────────────────────────────────┘
User Workflow (Using PIN)
1. User dials international number
2. System: "Enter your access PIN"
3. User enters: 1234#
4. PIN validated against "International Access" list
5. If valid → Call proceeds
6. If invalid → "Invalid PIN" → Hangup
Quick Tips
TIP
Unique PINs: Use different PINs per user for accountability tracking.
TIP
PIN Length: Use at least 4 digits for security.
CAUTION
Disabled vs. Deleted: Disable PINs for temporary revocation; delete only for permanent removal.
---
4. Configuration Fields Reference
PIN List Fields
| Field | Description | Example | Required |
|---|
| List Name | Unique identifier | International Access | Yes | |
| Description | Purpose notes | PINs for international | No | |
| Enabled | List active status | On/Off | Yes |
PIN Member Fields
| Field | Description | Example | Required |
|---|
| PIN | Access code | 1234 | Yes | |
| Description | Owner/purpose | John Smith | No | |
| Enabled | PIN active status | On/Off | Yes |
| Characters | Example | Notes |
|---|
| Digits 0-9 | 1234 | Standard | |
| Special # | 123# | Advanced | |
| Letters A-Z | ABC123 | Rare | |
| Max length | 16 chars | Configurable |
---
5. Call Flow / Logic Explanation
PIN Validation Flow
┌─────────────────────────────────────────────────────────────────┐
│ PIN Validation Flow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Dialplan triggers PIN validation │
│ session:execute("lua", "validate_pin.lua") │
│ with pin_list = "international" │
│ │ │
│ ▼ │
│ 2. Resolve domain_id from domain_name │
│ ├─ Found → Continue │
│ └─ Not found → "Feature not available" → Hangup │
│ │ │
│ ▼ │
│ 3. Look up PIN list by name │
│ SELECT id FROM public.pin_lists │
│ WHERE domain_id = X AND name = 'international' │
│ AND enabled = TRUE │
│ ├─ Found → Continue │
│ └─ Not found → "Feature not available" → Hangup │
│ │ │
│ ▼ │
│ 4. Prompt for PIN │
│ Play: "enter_pin.wav" │
│ Read: up to max_digits, timeout │
│ │ │
│ ▼ │
│ 5. Validate entered PIN │
│ SELECT 1 FROM public.pin_list_members │
│ WHERE pin_list_id = X AND pin = [input] AND enabled = TRUE │
│ │ │
│ ▼ │
│ 6. Set result │
│ ├─ Found → pin_list_valid = "true" → Continue call │
│ └─ Not found → pin_list_valid = "false" → Hangup │
│ │
└─────────────────────────────────────────────────────────────────┘
Channel Variables
| Variable | Direction | Description |
|---|
pin_list | Input | Name of PIN list to validate against | |
pin_max_digits | Input | Maximum PIN length (default: 6) | |
pin_timeout | Input | Milliseconds to wait for input (default: 5000) | |
pin_list_valid | Output | Result: "true" or "false" |
---
6. Import/Export Feature
CSV Export
Purpose: Backup PIN lists or migrate to another system.
Format:
name,description,pin,pinDescription,enabled
International Access,PINs for international,1234,John Smith,true
International Access,PINs for international,5678,Jane Doe,true
Sales Codes,Sales team access,9012,Sales Team,true
CSV Import
Import Modes:
| Mode | Behavior |
|---|
| Skip duplicates | Ignore existing lists, only create new | |
| Update existing | Update existing lists, create new ones | |
| Replace all | Delete all existing, import fresh |
Process:
- Click Import button
- Select CSV file
- Choose import mode
- Review row count
- Click Import
---
7. Common Scenarios & Examples
Scenario 1: International Dialing Control
PIN List:
| List Name | PINs |
|---|
| International Access | 1234 (CEO), 5678 (CFO), 9012 (Sales Dir) |
Dialplan:
<extension name="international-check">
<condition field="destination_number" expression="^011(.*)$">
<action application="set" data="pin_list=International Access"/>
<action application="lua" data="main/xml_handlers/pin/validate_pin.lua"/>
<action application="bridge" data="..."/>
</condition>
</extension>
Scenario 2: Department Cost Centers
Multiple Lists:
| List Name | Purpose |
|---|
| Sales PINs | Sales team calls | |
| Support PINs | Support team calls | |
| Executive PINs | Executive calls |
Tracking: Each PIN usage can be logged with the PIN description for billing.
Scenario 3: Temporary Guest Access
Setup:
| PIN | Description | Enabled |
|---|
| 8888 | Conference Room A | ✓ | |
| 9999 | Guest Access | ✓ |
Usage: Disable guest PIN after event ends.
---
8. Limitations & Important Notes
Technical Limitations
WARNING
PIN Uniqueness: PINs must be unique within a single list.
WARNING
Case Sensitivity: PINs are case-sensitive if using letters.
Best Practices
- Unique PINs Per User: For accountability
- Descriptive Names: "John Smith" not "PIN 1"
- Regular Audits: Review PIN lists quarterly
- Disable vs. Delete: Use disable for temporary revocation
- Strong PINs: Avoid 1234, 0000, 1111
Security Considerations
CAUTION
Shared PINs: Avoid sharing PINs between users—no accountability.
---
9. Troubleshooting Tips
Common Issues
| Symptom | Possible Cause | Solution |
|---|
| "Feature not available" | List not found/disabled | Check list name and enabled status | |
| "Invalid PIN" | PIN not found/disabled | Verify PIN exists and is enabled | |
| No prompt heard | Audio file missing | Check enter_pin.wav exists | |
| Always fails | Wrong list name | Verify dialplan pin_list variable |
Diagnostic SQL
List all PIN lists:
SELECT id, name, enabled,
(SELECT COUNT(*) FROM public.pin_list_members
WHERE pin_list_id = l.id) as pin_count
FROM public.pin_lists l
WHERE domain_id = [domain_id];
Check specific PIN:
SELECT l.name as list_name, m.pin, m.description, m.enabled
FROM public.pin_list_members m
JOIN public.pin_lists l ON m.pin_list_id = l.id
WHERE l.domain_id = [domain_id] AND m.pin = '1234';
---
10. Glossary
| Term | Definition |
|---|
| PIN List | A named collection of authorization codes | |
| PIN Member | An individual PIN within a list | |
| Authorization Code | Same as PIN—code entered for access | |
| pin_list_valid | Channel variable set after validation | |
| Multi-tenant | Each domain has separate PIN lists | |
| CSV Import | Bulk upload of PINs from spreadsheet |
---
Lua Script Status
✅ Implementation Verified
The Lua handler at telephony/freeswitch/lua/main/xml_handlers/pin/validate_pin.lua is correctly implemented:
| Check | Status |
|---|
Uses public. schema | ✅ Correct | |
| SQL injection protection | ✅ Uses escape() | |
| Multi-tenant support | ✅ Resolves domain_id | |
| Error handling | ✅ Proper logging | |
| Audio prompts | ✅ Uses langutil |
No fixes required.
---
Documentation last updated: January 2026