completed SMS gateway project

This commit is contained in:
Min Zeya Phyo
2025-10-22 17:22:17 +08:00
commit c883fa7128
190 changed files with 16294 additions and 0 deletions

757
ADMIN_COMPLETE.md Normal file
View File

@@ -0,0 +1,757 @@
# Complete Admin Interface Implementation
## Summary
This document summarizes all the work completed to build a full-featured admin interface for MySMSAPio, including API key management, gateway management, SMS logs, and QR code-based configuration.
---
## Features Implemented
### 1. ✅ Admin Authentication System
**What was built**:
- Secure login/logout system
- Session-based authentication
- Bcrypt password hashing
- Flash message support
- Helper methods for authentication checks
**Files created/modified**:
- `app/models/admin_user.rb` (renamed from `admin.rb` to avoid namespace conflict)
- `app/controllers/admin/base_controller.rb`
- `app/controllers/admin/sessions_controller.rb`
- `app/views/admin/sessions/new.html.erb`
- `app/helpers/application_helper.rb`
- Migration: `db/migrate/*_rename_admins_to_admin_users.rb`
**Access**:
- URL: `/admin/login`
- Default credentials: `admin@example.com` / `password123`
---
### 2. ✅ Professional UI with Tailwind CSS
**What was implemented**:
- Modern Tailwind CSS v4 design system
- Dark gradient sidebar navigation
- Responsive layouts (mobile/tablet/desktop)
- Font Awesome 6.4.0 icons
- Animated status indicators (pulse effects)
- Smooth transitions and hover effects
- Professional color scheme
**Visual Features**:
- Card-based layouts
- Badge components for status
- Table designs with hover effects
- Form styling with icons
- Button states and loading indicators
**Files**:
- `app/assets/tailwind/application.css`
- `app/views/layouts/admin.html.erb`
- All admin view files
---
### 3. ✅ Dashboard
**Features**:
- Real-time statistics:
- Total gateways (with online count)
- Active API keys count
- Messages sent today
- Messages received today
- Recent messages table (last 10)
- Gateway status overview
- Color-coded status badges
**URL**: `/admin/dashboard` or `/admin`
**Files**:
- `app/controllers/admin/dashboard_controller.rb`
- `app/views/admin/dashboard/index.html.erb`
---
### 4. ✅ API Keys Management
**Features**:
- List all API keys with:
- Name and key prefix
- Permissions (as badges)
- Active/Revoked/Expired status
- Last used timestamp
- Creation date
- Create new API keys:
- Name input
- Permission checkboxes (Send SMS, Receive SMS, Manage Gateways, Manage OTP)
- Optional expiration date
- One-time API key display:
- Full key shown only once after creation
- Copy to clipboard button with feedback
- Session-based security (not in URL)
- Revoke keys with confirmation
**URLs**:
- List: `/admin/api_keys`
- Create: `/admin/api_keys/new`
- Show (after creation): `/admin/api_keys/:id`
**Files**:
- `app/controllers/admin/api_keys_controller.rb`
- `app/views/admin/api_keys/index.html.erb`
- `app/views/admin/api_keys/new.html.erb`
- `app/views/admin/api_keys/show.html.erb`
**Security**:
- API keys are SHA256 hashed
- Raw keys shown only once
- Stored in session temporarily
- CSRF protection enabled
---
### 5. ✅ Gateway Management
**Features**:
**List Gateways** (`/admin/gateways`):
- Table showing all gateways
- Online/Offline status with animated pulse
- Active/Inactive toggles
- Priority levels
- Message statistics (today and total)
- Last heartbeat timestamps
- Device IDs
- "Register New Gateway" button
**Create Gateway** (`/admin/gateways/new`):
- Device ID input
- Gateway name input
- Priority selector (1-10)
- Automatic API key generation
- Info box explaining the process
**Gateway Success Page** (after creation):
- **QR Code Display**:
- High-quality SVG QR code
- Contains: API key, API base URL, WebSocket URL
- Scannable with Android app
- Auto-configuration support
- **Manual Configuration**:
- API Base URL (with copy button)
- WebSocket URL (with copy button)
- API Key (with copy button)
- "Copy All" button
- **Gateway Details**:
- Device ID, Name, Priority
- Status (offline until connected)
- Creation timestamp
- **Setup Instructions**:
- Option 1: QR code scanning (recommended)
- Option 2: Manual entry
- Step-by-step guide
**View Gateway Details** (`/admin/gateways/:id`):
- Connection status dashboard
- Statistics cards:
- Online/Offline status
- Active/Inactive status
- Priority level
- Messages sent/received today
- Total messages
- Gateway information:
- Device ID
- Name, Status, Priority
- Last heartbeat (with time ago)
- Message counters
- Creation/update timestamps
- Device metadata (JSON display)
- Recent messages table (last 20)
- Activate/Deactivate button
**Files**:
- `app/controllers/admin/gateways_controller.rb`
- `app/views/admin/gateways/index.html.erb`
- `app/views/admin/gateways/new.html.erb`
- `app/views/admin/gateways/show.html.erb`
**Dependencies**:
- `rqrcode` gem v2.0+ for QR code generation
---
### 6. ✅ SMS Logs
**Features**:
- Paginated message list (50 per page, using Pagy)
- Advanced filtering:
- Direction (Inbound/Outbound/All)
- Status (Pending/Sent/Delivered/Failed/All)
- Phone number search
- Gateway filter
- Date range (from/to)
- Search button
- Message display:
- Message ID (truncated with code style)
- Phone number
- Direction badge (Inbound/Outbound with icons)
- Status badge (color-coded)
- Gateway name (if assigned)
- Message preview (truncated)
- Retry count (if failed)
- Timestamp
- Expandable error messages (click to view full error)
- Empty state with helpful message
**URL**: `/admin/logs`
**Files**:
- `app/controllers/admin/logs_controller.rb`
- `app/views/admin/logs/index.html.erb`
---
### 7. ✅ QR Code Configuration System
**What was implemented**:
- Automatic QR code generation on gateway creation
- JSON payload with all configuration data:
```json
{
"api_key": "gw_live_...",
"api_base_url": "http://localhost:3000",
"websocket_url": "ws://localhost:3000/cable",
"version": "1.0"
}
```
- High error correction level (L=H)
- SVG format for quality scaling
- Automatic URL detection (HTTP→WS, HTTPS→WSS)
- Copy to clipboard for individual fields
- "Copy All" button for complete configuration
**Benefits**:
- No manual typing of long API keys
- Reduces configuration errors
- Faster gateway setup (scan QR code → done)
- Works offline (QR code doesn't need network)
**Gem Added**:
```ruby
gem "rqrcode", "~> 2.0"
```
---
## Bug Fixes Applied
### Issue 1: Namespace Conflict - "Admin is not a module"
**Problem**: Model class `Admin` conflicted with `Admin` module namespace
**Solution**:
- Renamed model: `Admin` → `AdminUser`
- Renamed table: `admins` → `admin_users`
- Updated all references in controllers, views, seeds, tests
**Files**:
- Migration: `20251020031401_rename_admins_to_admin_users.rb`
- Model: `app/models/admin_user.rb`
- All admin controllers
- `db/seeds.rb`
### Issue 2: undefined method 'flash'
**Problem**: Application in API-only mode disabled sessions and flash
**Solution**:
- Disabled `config.api_only = true` in `config/application.rb`
- Created `config/initializers/session_store.rb`
- API controllers use `ActionController::API` (fast, stateless)
- Admin controllers use `ActionController::Base` (full Rails features)
**Middleware Added**:
- ActionDispatch::Cookies
- ActionDispatch::Session::CookieStore
- ActionDispatch::Flash
### Issue 3: undefined method 'logged_in?'
**Problem**: Helper methods not available in layout before controller runs
**Solution**:
- Added `current_admin` and `logged_in?` to `ApplicationHelper`
- Methods now globally available in all views
### Issue 4: undefined method 'stringify_keys' for String
**Problem**: JSONB fields sometimes returned String instead of Hash, causing serialization errors
**Solution**:
- Added explicit attribute declarations to all models with JSONB fields:
- `ApiKey` - `permissions` field
- `Gateway` - `metadata` field
- `OtpCode` - `metadata` field
- `SmsMessage` - `metadata` field
- Added `before_validation :ensure_*_is_hash` callbacks
- Added defensive coding in views
**Pattern Applied**:
```ruby
class Model < ApplicationRecord
attribute :jsonb_field, :jsonb, default: {}
before_validation :ensure_jsonb_field_is_hash
private
def ensure_jsonb_field_is_hash
self.jsonb_field = {} if jsonb_field.nil?
self.jsonb_field = {} unless jsonb_field.is_a?(Hash)
end
end
```
### Issue 5: API Key Creation Stuck on /new Page
**Problem**: Form submission created key but didn't redirect properly
**Solution**:
- Changed from `render :show` to `redirect_to` pattern
- Added session storage for raw API key
- Added `show` action to controller
- Updated routes to include `:show`
**Same fix applied to Gateway creation for consistency**
---
## Architecture
### Hybrid Rails Application
```
MySMSAPio
├── API Endpoints (ActionController::API)
│ ├── Fast, stateless, token-based auth
│ ├── /api/v1/sms/*
│ ├── /api/v1/otp/*
│ └── /api/v1/gateway/*
└── Admin Interface (ActionController::Base)
├── Full Rails features, session-based auth
├── /admin/login
├── /admin/dashboard
├── /admin/api_keys
├── /admin/logs
└── /admin/gateways
```
### Database Schema Updates
**AdminUsers Table**:
```ruby
create_table "admin_users" do |t|
t.string :email, null: false, index: {unique: true}
t.string :password_digest, null: false
t.string :name, null: false
t.datetime :last_login_at
t.timestamps
end
```
**JSONB Fields** (all with `default: {}`):
- `api_keys.permissions` - API key permissions
- `gateways.metadata` - Gateway device metadata
- `otp_codes.metadata` - OTP metadata
- `sms_messages.metadata` - Message metadata
---
## Routes Summary
```ruby
namespace :admin do
# Authentication
get "login", to: "sessions#new"
post "login", to: "sessions#create"
delete "logout", to: "sessions#destroy"
# Dashboard
get "dashboard", to: "dashboard#index"
root to: "dashboard#index"
# API Keys
resources :api_keys, only: [:index, :new, :create, :show, :destroy] do
member { post :toggle }
end
# SMS Logs
resources :logs, only: [:index]
# Gateways
resources :gateways, only: [:index, :new, :create, :show] do
member { post :toggle }
end
end
```
---
## Dependencies Added
### Gems
```ruby
gem "tailwindcss-rails", "~> 4.3" # Already present
gem "rqrcode", "~> 2.0" # NEW - QR code generation
```
### External Libraries (CDN)
- Font Awesome 6.4.0 (icons)
---
## Configuration Files
### Key Files Created/Modified
**Config**:
- `config/application.rb` - Disabled API-only mode
- `config/initializers/session_store.rb` - Session configuration
- `config/routes.rb` - Admin routes
**Controllers**:
- `app/controllers/admin/base_controller.rb` - Base for all admin controllers
- `app/controllers/admin/sessions_controller.rb` - Login/logout
- `app/controllers/admin/dashboard_controller.rb` - Dashboard
- `app/controllers/admin/api_keys_controller.rb` - API key management
- `app/controllers/admin/logs_controller.rb` - SMS logs
- `app/controllers/admin/gateways_controller.rb` - Gateway management
**Models**:
- `app/models/admin_user.rb` - Admin authentication
- `app/models/api_key.rb` - Updated with JSONB fix
- `app/models/gateway.rb` - Updated with JSONB fix
- `app/models/otp_code.rb` - Updated with JSONB fix
- `app/models/sms_message.rb` - Updated with JSONB fix
**Views**:
- `app/views/layouts/admin.html.erb` - Admin layout with sidebar
- `app/views/admin/sessions/new.html.erb` - Login page
- `app/views/admin/dashboard/index.html.erb` - Dashboard
- `app/views/admin/api_keys/*.html.erb` - API key views (3 files)
- `app/views/admin/logs/index.html.erb` - SMS logs
- `app/views/admin/gateways/*.html.erb` - Gateway views (3 files)
**Helpers**:
- `app/helpers/application_helper.rb` - Auth helper methods
**Assets**:
- `app/assets/tailwind/application.css` - Custom Tailwind theme
**Seeds**:
- `db/seeds.rb` - Default admin user creation
---
## Security Features
### Authentication
✅ Bcrypt password hashing (cost: 12)
✅ Session-based login (cookie store)
✅ CSRF protection on all forms
✅ `before_action :require_admin` on all admin controllers
### API Keys
✅ SHA256 hashing before storage
✅ Raw keys shown only once
✅ Session-based temporary storage
✅ No keys in URLs or browser history
✅ HTTPS enforcement recommended for production
### Gateways
✅ Unique device ID enforcement
✅ API key generation with secure random
✅ QR code displayed only once
✅ WebSocket authentication required
### General
✅ SQL injection protection (ActiveRecord)
✅ XSS protection (ERB escaping)
✅ Mass assignment protection (strong parameters)
✅ Encrypted session cookies
---
## Documentation Created
1. `ADMIN_INTERFACE.md` - Complete admin documentation
2. `ADMIN_QUICKSTART.md` - Quick reference guide
3. `STARTUP_GUIDE.md` - Detailed startup instructions
4. `NAMESPACE_FIX.md` - Admin namespace conflict explanation
5. `SESSION_MIDDLEWARE_FIX.md` - Middleware configuration details
6. `PERMISSIONS_FIX.md` - JSONB permissions fix explanation
7. `JSONB_FIXES.md` - Complete JSONB field fixes documentation
8. `FIXES_APPLIED.md` - All fixes summary
9. `GATEWAY_MANAGEMENT.md` - Gateway management documentation
10. `QR_CODE_SETUP.md` - QR code implementation details
11. `ADMIN_COMPLETE.md` - This file (complete summary)
---
## Testing
### Manual Testing Checklist
- [x] Admin login works
- [x] Dashboard displays statistics
- [x] Can create API keys
- [x] API key displayed once after creation
- [x] Copy to clipboard works
- [x] Can revoke API keys
- [x] Can view SMS logs
- [x] Can filter SMS logs
- [x] Pagination works
- [x] Can register new gateway
- [x] QR code generated and displayed
- [x] Manual configuration copy buttons work
- [x] Can view gateway details
- [x] Can activate/deactivate gateways
- [x] Can toggle gateway status
- [x] Flash messages display correctly
- [x] Responsive design works on mobile
- [x] All icons display correctly
- [x] No stringify_keys errors
- [x] No JSONB serialization errors
### Console Testing
```bash
# Test admin login
bin/rails runner "puts AdminUser.first&.authenticate('password123') ? 'OK' : 'FAIL'"
# Test API key creation
bin/rails runner "
result = ApiKey.generate!(name: 'Test', permissions: {send_sms: true})
puts result[:raw_key]
"
# Test gateway creation
bin/rails runner "
gateway = Gateway.new(device_id: 'test-001', name: 'Test', priority: 1, status: 'offline')
key = gateway.generate_api_key!
puts key
"
# Test JSONB fields
bin/rails runner "
puts ApiKey.first.permissions.class # Should be Hash
puts Gateway.first.metadata.class # Should be Hash
"
```
---
## Production Deployment Checklist
### Before Deploying
- [ ] Change default admin password
- [ ] Set `config.force_ssl = true` in production.rb
- [ ] Set secure `SECRET_KEY_BASE`
- [ ] Configure proper `ALLOWED_ORIGINS` for CORS
- [ ] Set up proper database backups
- [ ] Configure Redis for production
- [ ] Set up SSL certificates (Let's Encrypt)
- [ ] Configure proper logging
- [ ] Set up monitoring (e.g., New Relic, Datadog)
- [ ] Test all features in staging first
### Environment Variables
```bash
DATABASE_URL=postgresql://...
REDIS_URL=redis://...
SECRET_KEY_BASE=...
RAILS_ENV=production
RAILS_LOG_TO_STDOUT=enabled
RAILS_SERVE_STATIC_FILES=enabled
```
### Security Settings
```ruby
# config/environments/production.rb
config.force_ssl = true
config.action_controller.default_url_options = { host: 'api.example.com', protocol: 'https' }
```
---
## Performance Considerations
### Database Indexes
All critical queries have indexes:
- `admin_users.email` (unique)
- `api_keys.key_digest` (unique)
- `api_keys.key_prefix`
- `gateways.device_id` (unique)
- `sms_messages.message_id` (unique)
- `sms_messages.status`
- `sms_messages.phone_number`
### Pagination
- SMS logs: 50 per page (using Pagy)
- Recent messages: Limited to 20
- Can be adjusted in controllers
### Caching Opportunities
Not yet implemented, but recommended:
- Dashboard statistics (cache for 5 minutes)
- Gateway list (cache for 1 minute)
- API key count (cache for 5 minutes)
---
## Future Enhancements
### Potential Improvements
1. **API Key Features**:
- Edit API key permissions
- API key usage statistics
- Rate limiting configuration per key
- Key rotation/regeneration
2. **Gateway Features**:
- Edit gateway details (name, priority)
- Gateway health alerts
- Multiple device support per gateway
- Gateway groups/tags
3. **Logs Features**:
- Export logs (CSV, JSON)
- Advanced search (regex, wildcards)
- Log retention policies
- Real-time log streaming
4. **Dashboard**:
- Charts and graphs (Chart.js)
- Customizable widgets
- Date range selection
- Export reports
5. **User Management**:
- Multiple admin users
- Role-based permissions (super admin, viewer, etc.)
- Audit logs for admin actions
- Two-factor authentication
6. **Notifications**:
- Email alerts for gateway offline
- SMS delivery failure alerts
- Daily/weekly reports
- Webhook integrations
---
## Summary
### What Was Achieved
✅ **Complete Admin Interface**: Fully functional web-based admin panel
✅ **Authentication**: Secure session-based login with bcrypt
✅ **Professional Design**: Modern Tailwind CSS UI with responsive layout
✅ **API Key Management**: Create, view, revoke with one-time display
✅ **Gateway Management**: Register, configure, monitor SMS gateways
✅ **QR Code Setup**: Instant configuration via QR code scanning
✅ **SMS Logs**: Advanced filtering and pagination
✅ **Dashboard**: Real-time statistics and overview
✅ **Bug Fixes**: All namespace, session, and JSONB issues resolved
✅ **Documentation**: Comprehensive guides and references
✅ **Security**: CSRF protection, password hashing, key encryption
✅ **Production Ready**: Deployable with Kamal/Docker
### Total Files Created/Modified
- **Controllers**: 6 files
- **Models**: 5 files (4 updated, 1 created)
- **Views**: 15+ files
- **Migrations**: 2 files
- **Initializers**: 1 file
- **Routes**: 1 file (updated)
- **Assets**: 1 file
- **Documentation**: 11 markdown files
- **Gemfile**: 1 gem added
- **Seeds**: 1 file (updated)
### Lines of Code
Approximately **3,500+ lines** of Ruby, ERB, CSS, and JavaScript code written.
---
## Quick Start
### First Time Setup
```bash
# Install dependencies
bundle install
# Setup database
bin/rails db:migrate
bin/rails db:seed
# Start server
bin/dev
```
### Access Admin Interface
```
URL: http://localhost:3000/admin/login
Email: admin@example.com
Password: password123
```
### Create First API Key
1. Login to admin
2. Click "API Keys" in sidebar
3. Click "Create New API Key"
4. Fill form and submit
5. Copy the API key (shown only once!)
### Register First Gateway
1. Click "Gateways" in sidebar
2. Click "Register New Gateway"
3. Fill form and submit
4. Scan QR code with Android app OR copy configuration manually
5. Start gateway service in app
6. Gateway will show "Online" when connected
---
## Support
For issues or questions:
- Check documentation in project root
- Review code comments
- Check Rails logs: `tail -f log/development.log`
- Use Rails console for debugging: `bin/rails console`
---
**Status**: ✅ COMPLETE - All features implemented and tested
**Last Updated**: October 20, 2025