Skip to content

Repository files navigation

🗳️ RemoteVote NG — Backend API

Django REST Framework backend powering the RemoteVote NG electronic voting platform. Provides the full electoral management API including voter identity verification, election lifecycle management, result collation, staff onboarding, accreditation, and an audit trail.


📋 Table of Contents


Overview

RemoteVote NG is a simulated national e-voting infrastructure built for the Nigerian electoral context. The backend implements:

  • NIMC Identity Verification — NIN-based biometric identity matching at the point of accreditation
  • Multi-role RBAC — Granular permissions for 13 distinct user roles across INEC HQ and field levels
  • Full Election Lifecycledrafted → upcoming → active → collation → closed state machine
  • Cryptographic Audit Trail — Every CRUD operation is automatically logged via Django signals
  • Staff Onboarding — Token-based invitation system for pre-provisioning electoral officials
  • Result Sheet Upload — Digital equivalent of INEC Form EC8A with overvoting detection
  • Bulk CSV Operations — Import/export support for polling units, NIMC records, and invitations

Tech Stack

Layer Technology
Framework Django 4.2+
API Django REST Framework 3.14+
Auth DRF Token Authentication
Database (dev) SQLite 3
Database (prod) PostgreSQL (via Prisma Postgres / Neon)
CORS django-cors-headers
DB Switching dj-database-url
Email Brevo (Sendinblue) Transactional API
Config python-dotenv
Deployment Vercel (Python serverless)

Project Structure

backend/
├── api/
│   ├── management/
│   │   └── commands/
│   │       └── seed_data.py        # Database seeder (200+ records per model)
│   ├── migrations/                 # Django migrations
│   │   └── 0005_provision_secretary.py  # Auto-provisions INEC Secretary account
│   ├── admin.py                    # Django admin configuration
│   ├── auth_backend.py             # Custom NIN/Staff ID auth backend
│   ├── brevo.py                    # Brevo transactional email helpers
│   ├── middleware.py               # Thread-local request user capture (for audit logs)
│   ├── models.py                   # All data models
│   ├── serializers.py              # DRF serializers
│   ├── signals.py                  # Auto audit logging via post_save / post_delete
│   ├── tests.py                    # Unit test suite
│   ├── urls.py                     # App URL patterns
│   └── views.py                    # All API views
├── backend/
│   ├── settings.py                 # Project settings (env-driven)
│   ├── urls.py                     # Root URL config
│   └── wsgi.py                     # WSGI entrypoint (Vercel compatible)
├── vercel.json                     # Vercel deployment configuration
├── requirements.txt                # Python dependencies
└── .env                            # Environment variables (not committed)

Data Models

Model Description
NIMCRecord Simulated NIMC identity database (NIN + biometric hash)
PollingUnit Geographic polling locations with autogenerated PU-XXXXXX IDs
ElectoralUser Extended AbstractUser with 13-role RBAC and autogenerated staff numbers
OTPVerification MFA tokens for signup, password reset, and ballot authorization
Election Full lifecycle election with type classification and eligible-states filtering
Candidate Party candidates linked to elections
ResultSheet Digital Form EC8A with overvoting enforcement
DisputeLog Agent/observer dispute flag submissions
ElectionParticipation One-person-one-vote enforcement (unique voter + election)
AuditLog Automatic CRUD audit trail via Django signals
StaffInvitation Secure token-based pre-provisioning for electoral staff
AccreditationApplication Portal for media, domestic and international observers
ElectionClosureApproval Multi-signature election closure enforcement

API Endpoints

Auth

Method Endpoint Description
POST /api/auth/signup/ Register a new voter (NIN + NIMC verification)
POST /api/auth/login/ Login with NIN or Staff ID + password
POST /api/auth/verify-otp/ Verify OTP for MFA flows
POST /api/auth/request-otp/ Request a new OTP
POST /api/auth/reset-password/ Password reset
GET /api/auth/me/ Get current authenticated user profile
PATCH /api/auth/me/ Update profile

Elections

Method Endpoint Description
GET /api/elections/ List public/active elections (voters)
GET/POST /api/commissioner/elections/ Commissioner election management
POST /api/commissioner/elections/<id>/advance/ Advance election status
DELETE /api/commissioner/elections/<id>/delete/ Delete a drafted election
POST /api/commissioner/elections/<id>/candidates/ Add candidate
DELETE /api/commissioner/elections/<id>/candidates/<cid>/remove/ Remove candidate
POST /api/vote/ Cast a vote
GET /api/results/<id>/ Get election results

Polling Units

Method Endpoint Description
GET/POST /api/polling-units/ List or create polling units (bulk POST supported)
PUT/PATCH/DELETE /api/polling-units/<id>/ Update or delete a polling unit

NIMC Records

Method Endpoint Description
GET/POST /api/nimc-records/ List or create NIMC records (bulk POST supported)
PUT/PATCH/DELETE /api/nimc-records/<id>/ Update or delete a NIMC record

Staff Onboarding

Method Endpoint Description
POST /api/onboarding/invite/ Send staff invitation (bulk array supported)
GET /api/onboarding/invitations/ List all staff invitations
POST /api/onboarding/invite/<pk>/resend/ Resend an invitation
GET /api/onboarding/accept/<token>/ Accept a staff invitation
POST /api/onboarding/accreditation/ Submit accreditation application
POST /api/onboarding/accreditation/<pk>/review/ Review an accreditation

Secretary & Audit

Method Endpoint Description
GET /api/secretary/metrics/ Dashboard metrics for INEC Secretary
GET /api/audit-logs/ Full system audit trail
GET /api/result-sheets/ View result sheets
POST /api/disputes/ File a dispute

Authentication

The API uses DRF Token Authentication. Include the token in the Authorization header:

Authorization: Token <your_auth_token>

Tokens are returned on successful login via /api/auth/login/.

The custom auth backend (auth_backend.py) supports login with either:

  • NIN (National Identification Number) — for voters
  • Staff ID — for INEC staff

Environment Variables

Create a .env file in the backend/ directory:

# Django
DJANGO_SECRET_KEY=your-super-secret-key-here
DJANGO_DEBUG=True

# Database (leave empty for local SQLite, set for PostgreSQL in production)
DATABASE_URL=

# INEC Secretary Default Account (provisioned on first migration)
SECRETARY_NIN=99999999999
SECRETARY_STAFFID=STAFF-SECRETARY-2026
SECRETARY_DEFAULT_PASSWORD=SecPass2026!
SECRETARY_EMAIL=secretary@remotevoteng.org
SECRETARY_NAME=INEC Secretary HQ
SECRETARY_STATE=FCT
SECRETARY_LGA=Abuja Municipal

# Brevo Transactional Email
BREVO_API_KEY=your-brevo-api-key
BREVO_SENDER_EMAIL=noreply@remotevoteng.org
BREVO_SENDER_NAME=RemoteVote NG

# Frontend URL (for email links)
FRONTEND_URL=http://localhost:3000

---

## Frontend Integration

- **API base path:** `/api/` (example local backend: `http://localhost:8000/api/`).
- **Auth flow / endpoints:**
	- Register: `POST /api/auth/register/` (send NIN and user details)
	- Verify OTP: `POST /api/auth/verify-otp/` (NIN + code)
	- Login: `POST /api/auth/login/` (voter_id or staff_id + password)
		- Note: For staff, the frontend must send the field name `staff_id` containing the staff number (e.g. `STAFF-PO-001`). Do NOT send `staffid` or other variants — the backend expects `staff_id`.
	- Forgot password: `POST /api/auth/forgot-password/` (NIN)
	- Reset password: `POST /api/auth/reset-password/` (NIN + code + new password)
	- Profile: `GET /api/auth/profile/` (authenticated)
- **Auth header:** Include token on protected requests:

```http
Authorization: Token <your_auth_token>
  • Activation links: The backend uses FRONTEND_URL to compose invitation/activation links, e.g. ${FRONTEND_URL}/onboard?token=<token>; ensure the frontend route /onboard reads token from query parameters and calls the accept endpoint.

  • CORS: Development allows all origins (CORS_ALLOW_ALL_ORIGINS=True). For production, set explicit allowed origins matching the deployed frontend.

  • Error handling: Login may return code: "unverified" when OTP verification is required — present the OTP entry UI and call POST /api/auth/verify-otp/.

  • Example login (fetch):

fetch('http://localhost:8000/api/auth/login/', {
	method: 'POST',
	headers: { 'Content-Type': 'application/json' },
	// Voter login example
	// body: JSON.stringify({ voter_id: 'VOTER-XXXX', password: 'pass' })
	// Staff login example (use staff_id):
	body: JSON.stringify({ staff_id: 'STAFF-PO-001', password: 'Password2026!' })
})
.then(r => r.json())
.then(data => console.log(data))
  • Frontend env: The frontend only needs to know its own public FRONTEND_URL (used server-side to generate links) and the backend base URL during development.

---

## Getting Started (Local Development)

### Prerequisites
- Python 3.10+
- pip

### Setup

```bash
# 1. Navigate to the backend directory
cd backend

# 2. Create and activate virtual environment
python -m venv venv
venv\Scripts\activate        # Windows
# source venv/bin/activate   # macOS/Linux

# 3. Install dependencies
pip install -r requirements.txt

# 4. Create your .env file (see Environment Variables above)
cp .env.example .env

# 5. Apply database migrations
python manage.py migrate

# 6. Start the development server
python manage.py runserver

The API will be available at http://localhost:8000/api/


Database

Development (SQLite)

SQLite is used automatically when DATABASE_URL is not set in .env. The database file is stored at backend/db.sqlite3.

Note: When running tests, the backend always uses SQLite regardless of DATABASE_URL to ensure fast, isolated test runs.

Production (PostgreSQL)

Set the DATABASE_URL environment variable to your PostgreSQL connection string:

DATABASE_URL=postgresql://user:password@host:5432/dbname

Seeding the Database

Populate the database with realistic Nigerian mock data:

# Seed with 200+ records per model
python manage.py seed_data

# Clear existing data and re-seed fresh
python manage.py seed_data --clear

What gets seeded:

Model Count
NIMCRecord 250
PollingUnit 250
ElectoralUser (staff) ~220 across all roles
ElectoralUser (voters) ~200
Election 6 (Presidential, Senate, House, Governorship ×2, Assembly)
Candidate 5–7 per election
ResultSheet 200
DisputeLog 200
ElectionParticipation 200
StaffInvitation 200
AccreditationApplication 200

Default seed passwords:

  • Staff: Password2026!
  • Voters: Voter2026!
  • Secretary: configured via .env (default: SecPass2026!)

Running Tests

python manage.py test

All tests run against an isolated local SQLite database. The test suite covers:

  • Voter signup and NIN verification
  • OTP generation and validation
  • Staff invitation flow
  • Audit log signal handling
  • Election participation constraints

Deployment (Vercel)

The backend is configured for serverless deployment on Vercel via vercel.json in the backend/ directory.

Steps:

  1. Push the backend/ folder to a GitHub repository
  2. Connect the repository to Vercel
  3. Set the Root Directory to backend
  4. Add all .env variables to Vercel's Environment Variables dashboard
  5. Deploy — Vercel will auto-detect the Python runtime

Run migrations on first deploy:

# Via Vercel CLI or a one-time build hook
python manage.py migrate

The INEC Secretary account is automatically provisioned during the migration run.


Role-Based Access Control

Role Code Description
Registered Voter voter Can authenticate and cast votes
Prospective prospective Pre-registration state
Commissioner commissioner Creates/manages elections and candidates
Secretary secretary Full system oversight + metrics dashboard
Presiding Officer po Submits Form EC8A result sheets
Asst. Presiding Officer apo Field support role
Supervisory P.O. spo Supervises multiple polling units
Collation Officer co Collates ward-level results
Returning Officer ro Signs off on multi-level collation
Party Agent agent Monitors polling on behalf of parties
Media media Accredited press personnel
Observer observer Domestic/international election observer
Auditor auditor Cybersecurity and system audit access

License

MIT © RemoteVote NG — Studio3 Launchpad 2026

About

A civicTech Platform focused on improving election accessibility and participation

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages