completed SMS gateway project
This commit is contained in:
378
GATEWAY_MANAGEMENT.md
Normal file
378
GATEWAY_MANAGEMENT.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# Gateway Management - Admin Interface
|
||||
|
||||
## Overview
|
||||
|
||||
The admin interface now includes complete gateway management functionality, allowing administrators to register new Android SMS gateway devices and manage existing ones.
|
||||
|
||||
## Features Added
|
||||
|
||||
### 1. Register New Gateway
|
||||
|
||||
**URL**: `/admin/gateways/new`
|
||||
|
||||
**Form Fields**:
|
||||
- **Device ID** (required): Unique identifier for the gateway device
|
||||
- **Gateway Name** (required): Friendly name for identification
|
||||
- **Priority** (1-10): Priority level for message routing (higher priority = used first)
|
||||
|
||||
**Process**:
|
||||
1. Admin fills out the registration form
|
||||
2. System creates gateway record with status "offline"
|
||||
3. System generates unique API key (format: `gw_live_...`)
|
||||
4. Redirects to gateway details page showing the API key
|
||||
|
||||
### 2. Gateway Creation Success Page
|
||||
|
||||
After creating a gateway, the admin sees:
|
||||
|
||||
**Key Information Displayed**:
|
||||
- ✅ Warning banner: "Save this API key now - you won't see it again!"
|
||||
- ✅ Gateway API key in copy-to-clipboard format
|
||||
- ✅ Gateway details (Device ID, Name, Priority, Status)
|
||||
- ✅ Next steps instructions for configuring the Android app
|
||||
|
||||
**Copy to Clipboard**:
|
||||
- Click button to copy API key
|
||||
- Visual feedback (button turns green, shows "Copied!")
|
||||
- API key displayed in terminal-style format (dark background, green text)
|
||||
|
||||
### 3. Gateway List Page
|
||||
|
||||
**URL**: `/admin/gateways`
|
||||
|
||||
**Features**:
|
||||
- "Register New Gateway" button (top right)
|
||||
- Table showing all gateways with:
|
||||
- Name (clickable link to details)
|
||||
- Device ID
|
||||
- Status (Online/Offline with animated pulse for online)
|
||||
- Active/Inactive status
|
||||
- Priority level
|
||||
- Today's message counts
|
||||
- Total message counts
|
||||
- Last heartbeat timestamp
|
||||
- Created date
|
||||
- Actions (View Details, Toggle Active)
|
||||
|
||||
### 4. Gateway Details Page (Existing Gateway)
|
||||
|
||||
**URL**: `/admin/gateways/:id`
|
||||
|
||||
**For existing gateways** (not newly created):
|
||||
- Complete statistics dashboard
|
||||
- Connection status indicators
|
||||
- Message statistics (sent/received today and total)
|
||||
- Recent messages table
|
||||
- Device metadata (if available)
|
||||
- Activate/Deactivate button
|
||||
|
||||
---
|
||||
|
||||
## API Key Security
|
||||
|
||||
### Key Generation
|
||||
|
||||
```ruby
|
||||
# Format: gw_live_ + 64 character hex string
|
||||
raw_key = "gw_live_#{SecureRandom.hex(32)}"
|
||||
api_key_digest = Digest::SHA256.hexdigest(raw_key)
|
||||
```
|
||||
|
||||
**Security Features**:
|
||||
- Raw key shown only once during creation
|
||||
- Stored as SHA256 hash in database
|
||||
- Keys cannot be retrieved after creation
|
||||
- Unique per gateway
|
||||
|
||||
### Session-Based Key Display
|
||||
|
||||
Similar to API key creation, gateway keys use session storage:
|
||||
|
||||
```ruby
|
||||
# On create:
|
||||
session[:new_gateway_id] = gateway.id
|
||||
session[:new_gateway_raw_key] = raw_key
|
||||
|
||||
# On show:
|
||||
if session[:new_gateway_id] == @gateway.id && session[:new_gateway_raw_key].present?
|
||||
@raw_key = session[:new_gateway_raw_key]
|
||||
@is_new = true
|
||||
# Clear session immediately
|
||||
session.delete(:new_gateway_id)
|
||||
session.delete(:new_gateway_raw_key)
|
||||
end
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Prevents accidental key exposure via URL
|
||||
- One-time display only
|
||||
- Secure redirect pattern
|
||||
- No key in browser history
|
||||
|
||||
---
|
||||
|
||||
## Routes Added
|
||||
|
||||
```ruby
|
||||
resources :gateways, only: [:index, :new, :create, :show] do
|
||||
member do
|
||||
post :toggle
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**Available Routes**:
|
||||
- `GET /admin/gateways` - List all gateways
|
||||
- `GET /admin/gateways/new` - New gateway form
|
||||
- `POST /admin/gateways` - Create gateway
|
||||
- `GET /admin/gateways/:id` - View gateway details (or show new key)
|
||||
- `POST /admin/gateways/:id/toggle` - Activate/deactivate gateway
|
||||
|
||||
---
|
||||
|
||||
## Controller Actions
|
||||
|
||||
### `new`
|
||||
Renders the registration form with empty gateway object.
|
||||
|
||||
### `create`
|
||||
```ruby
|
||||
def create
|
||||
@gateway = Gateway.new(
|
||||
device_id: params[:gateway][:device_id],
|
||||
name: params[:gateway][:name],
|
||||
priority: params[:gateway][:priority] || 1,
|
||||
status: "offline"
|
||||
)
|
||||
|
||||
raw_key = @gateway.generate_api_key!
|
||||
|
||||
# Store in session
|
||||
session[:new_gateway_id] = @gateway.id
|
||||
session[:new_gateway_raw_key] = raw_key
|
||||
|
||||
redirect_to admin_gateway_path(@gateway)
|
||||
end
|
||||
```
|
||||
|
||||
**Error Handling**:
|
||||
- Validates device_id uniqueness
|
||||
- Validates required fields
|
||||
- Shows error messages on form
|
||||
- Logs errors for debugging
|
||||
|
||||
### `show`
|
||||
Conditional rendering based on `@is_new`:
|
||||
|
||||
**If newly created**:
|
||||
- Shows API key with copy button
|
||||
- Shows basic gateway info
|
||||
- Shows next steps instructions
|
||||
- No statistics (gateway not connected yet)
|
||||
|
||||
**If existing gateway**:
|
||||
- Shows full statistics dashboard
|
||||
- Shows recent messages
|
||||
- Shows device metadata
|
||||
- Shows activate/deactivate controls
|
||||
|
||||
---
|
||||
|
||||
## Gateway Model
|
||||
|
||||
### Required Fields
|
||||
```ruby
|
||||
validates :device_id, presence: true, uniqueness: true
|
||||
validates :api_key_digest, presence: true
|
||||
validates :status, inclusion: { in: %w[online offline error] }
|
||||
```
|
||||
|
||||
### Default Values
|
||||
- `status`: "offline"
|
||||
- `priority`: 1
|
||||
- `active`: true
|
||||
- `metadata`: {} (empty JSONB hash)
|
||||
- Message counters: 0
|
||||
|
||||
### Methods
|
||||
|
||||
**`generate_api_key!`**:
|
||||
```ruby
|
||||
def generate_api_key!
|
||||
raw_key = "gw_live_#{SecureRandom.hex(32)}"
|
||||
self.api_key_digest = Digest::SHA256.hexdigest(raw_key)
|
||||
save!
|
||||
raw_key
|
||||
end
|
||||
```
|
||||
|
||||
**`online?`**:
|
||||
Checks if gateway is truly online based on heartbeat:
|
||||
```ruby
|
||||
def online?
|
||||
status == "online" && last_heartbeat_at.present? && last_heartbeat_at > 2.minutes.ago
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## View Files Created/Modified
|
||||
|
||||
### New Files
|
||||
- `app/views/admin/gateways/new.html.erb` - Registration form
|
||||
|
||||
### Modified Files
|
||||
- `app/views/admin/gateways/index.html.erb` - Added "Register New Gateway" button
|
||||
- `app/views/admin/gateways/show.html.erb` - Added conditional for new gateway display
|
||||
|
||||
---
|
||||
|
||||
## Usage Flow
|
||||
|
||||
### Registering a New Gateway
|
||||
|
||||
1. **Navigate to Gateways**
|
||||
- Click "Gateways" in sidebar
|
||||
- See list of existing gateways (if any)
|
||||
|
||||
2. **Start Registration**
|
||||
- Click "Register New Gateway" button (top right)
|
||||
- Form appears with 3 fields
|
||||
|
||||
3. **Fill Form**
|
||||
- Device ID: `phone-samsung-001`
|
||||
- Gateway Name: `Office Android Phone`
|
||||
- Priority: `5` (1-10 scale)
|
||||
|
||||
4. **Submit**
|
||||
- Click "Register Gateway" button
|
||||
- System creates gateway and generates API key
|
||||
|
||||
5. **Save API Key**
|
||||
- Warning shown: "Save this key now!"
|
||||
- API key displayed: `gw_live_a6e2b250dade...`
|
||||
- Click "Copy to Clipboard" button
|
||||
- Key copied to clipboard
|
||||
|
||||
6. **Configure Android App**
|
||||
- Follow "Next Steps" instructions
|
||||
- Install Android SMS Gateway app
|
||||
- Paste API key in app settings
|
||||
- Start gateway service
|
||||
|
||||
7. **Verify Connection**
|
||||
- Gateway appears "Offline" initially
|
||||
- Once Android app connects, status changes to "Online"
|
||||
- View gateway details to see statistics
|
||||
|
||||
---
|
||||
|
||||
## Next Steps Instructions (Shown on Success Page)
|
||||
|
||||
1. Copy the API key above using the "Copy to Clipboard" button
|
||||
2. Install the Android SMS Gateway app on your device
|
||||
3. Open the app and navigate to Settings
|
||||
4. Paste the API key in the app's configuration
|
||||
5. Save the configuration and start the gateway service
|
||||
6. The gateway will appear as "Online" once it connects successfully
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Console Test
|
||||
```bash
|
||||
bin/rails console
|
||||
```
|
||||
|
||||
```ruby
|
||||
# Create gateway
|
||||
gateway = Gateway.new(
|
||||
device_id: "test-001",
|
||||
name: "Test Gateway",
|
||||
priority: 3,
|
||||
status: "offline"
|
||||
)
|
||||
|
||||
# Generate API key
|
||||
raw_key = gateway.generate_api_key!
|
||||
puts "API Key: #{raw_key}"
|
||||
|
||||
# Verify
|
||||
gateway.reload
|
||||
puts "Gateway ID: #{gateway.id}"
|
||||
puts "Device ID: #{gateway.device_id}"
|
||||
puts "Key Digest: #{gateway.api_key_digest}"
|
||||
```
|
||||
|
||||
### Browser Test
|
||||
1. Start server: `bin/dev`
|
||||
2. Visit: `http://localhost:3000/admin/login`
|
||||
3. Login with admin credentials
|
||||
4. Click "Gateways" in sidebar
|
||||
5. Click "Register New Gateway"
|
||||
6. Fill form and submit
|
||||
7. Verify API key is displayed
|
||||
8. Verify copy to clipboard works
|
||||
9. Click "Back to Gateways"
|
||||
10. Verify new gateway appears in list
|
||||
|
||||
---
|
||||
|
||||
## Integration with Android App
|
||||
|
||||
The gateway API key is used by the Android app to:
|
||||
|
||||
1. **Authenticate WebSocket Connection**
|
||||
- Connect to: `ws://your-server.com/cable?api_key=gw_live_...`
|
||||
- Connection class authenticates via `api_key_digest`
|
||||
|
||||
2. **Send Heartbeats**
|
||||
- POST `/api/v1/gateway/heartbeat`
|
||||
- Header: `Authorization: Bearer gw_live_...`
|
||||
- Keeps gateway status "online"
|
||||
|
||||
3. **Report Received SMS**
|
||||
- POST `/api/v1/gateway/sms/received`
|
||||
- Header: `Authorization: Bearer gw_live_...`
|
||||
- Sends inbound SMS to system
|
||||
|
||||
4. **Report Delivery Status**
|
||||
- POST `/api/v1/gateway/sms/status`
|
||||
- Header: `Authorization: Bearer gw_live_...`
|
||||
- Updates message delivery status
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Production Checklist
|
||||
- ✅ API keys are SHA256 hashed before storage
|
||||
- ✅ Raw keys shown only once during creation
|
||||
- ✅ Keys transmitted via session (not URL)
|
||||
- ✅ Device ID uniqueness enforced
|
||||
- ✅ CSRF protection enabled on all forms
|
||||
- ⚠️ Ensure HTTPS in production (`config.force_ssl = true`)
|
||||
- ⚠️ Secure WebSocket connections (wss://)
|
||||
- ⚠️ Implement rate limiting on registration endpoint
|
||||
|
||||
### Recommended Practices
|
||||
- Regularly audit gateway list
|
||||
- Deactivate unused gateways
|
||||
- Monitor heartbeat timestamps
|
||||
- Alert on prolonged offline status
|
||||
- Rotate keys if device is compromised
|
||||
- Keep device firmware updated
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
✅ **Complete Gateway Management**: Register, view, and manage SMS gateway devices
|
||||
✅ **Secure API Key Generation**: One-time display with copy-to-clipboard
|
||||
✅ **Professional UI**: Tailwind CSS styling with clear instructions
|
||||
✅ **Session-Based Security**: Keys not exposed in URLs or browser history
|
||||
✅ **Integration Ready**: Works with Android SMS Gateway app
|
||||
✅ **Admin Controls**: Activate/deactivate, view statistics, monitor status
|
||||
|
||||
The admin interface now provides everything needed to manage SMS gateway devices from registration to monitoring!
|
||||
Reference in New Issue
Block a user