Skip to content

dankeg/AidMap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

5 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

AidMap logo

AidMap

Crowdsourced locations of first-aid kits, AEDs, and other emergency supplies.

Website Build Issues PRs Python Flask License


AidMap is a lightweight Flask application that lets communities crowdsource the locations of critical emergency resourcesโ€”like first-aid kits, AEDs, and general emergency kitsโ€”onto an interactive Mapbox map. Submissions can include photos, are vetted via a built-in moderator workflow with optional two-factor authentication, and can be upvoted to highlight the most useful entries.

  • Live site: aidmap.live
  • Tech: Python + Flask, SQLite, Mapbox GL JS
  • Topics: crowdsourcing, emergency-response, first aid, mapping

๐Ÿ“š Contents


๐Ÿงฉ Features

Crowdsourced Submissions

  • Users submit latitude/longitude, resource type, description, and optional image (PNG/JPEG).

Moderator Workflow

  • Password-based moderator login with optional TOTP 2FA (Google Authenticator compatible).
  • Approve or reject pending submissions.

Voting

  • Simple per-browser voting with lookback window to reduce repeat votes.

Map-based UI

  • Mapbox-powered interactive map showing approved resources, colored by type.

Configurable Resource Categories

  • Update labels and colors in a JSON file without code changes.

Sensible Defaults & Security

  • Strict content security policy, file size limits, MIME checks, and session scoping.

โšก Quickstart

Prerequisites

Local Run

Clone and install:

git clone https://github.com/dankeg/AidMap.git
cd AidMap
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

Set environment:

export MAPBOX_TOKEN="pk.your-mapbox-token"
# Optional but recommended for local moderation:
export ADMIN_USERNAME="admin"
export ADMIN_PASSWORD="choose-a-strong-password"
# Optional: bootstrap credentials path
# export ADMIN_BOOTSTRAP_PATH="$PWD/temp_credentials.txt"

Start the app:

python app.py
# or with Gunicorn (recommended for prod-like runs)
gunicorn -c gunicorn_config.py app:app

Open http://127.0.0.1:5000


โš™๏ธ Configuration

Environment Variables

Variable Required Description
MAPBOX_TOKEN โœ… Mapbox access token used by frontend
ADMIN_USERNAME โŒ (default: admin) Moderator username
ADMIN_PASSWORD โŒ If unset, random credentials are generated
ADMIN_BOOTSTRAP_PATH โŒ (default: temp_credentials.txt) File to store bootstrap credentials

Other in-code defaults:

  • MAX_CONTENT_LENGTH = 16MB
  • SESSION lifetime = 2 hours
  • Allowed MIME types: image/jpeg, image/jpg, image/png

Moderator 2FA (TOTP)

  • If ADMIN_PASSWORD is unset on first run, one-time credentials and a new TOTP secret are generated.
  • If set, moderators can enable 2FA via the moderator UI.

๐Ÿง  API

Public Endpoints

Method Route Description
GET /api/submissions Returns approved submissions
GET /api/submissions/{id}/image Returns base64 image + MIME type
POST /api/submit Submit new location (multipart/form-data)
POST /api/vote/{submission_id} One vote per browser (30-day window)

Moderator Endpoints

Method Route Description
POST /api/moderator/login Login, returns 2FA flag
POST /api/moderator/login/totp Verify TOTP
POST /api/moderator/logout Logout moderator
GET /api/moderator/pending List pending submissions
POST /api/moderator/approve/{id} Approve submission
POST /api/moderator/reject/{id} Reject (delete) submission

๐Ÿ—ƒ๏ธ Data Model

  • SQLite database at instance/medical_supplies.db
  • Schema: see schema.sql

Tables

  • submissions: entries with status, votes, timestamps, optional image blob
  • votes: unique (submission_id, vote_token) with 30-day enforcement
  • moderators: username, password hash, optional TOTP secret

Reset Database

rm instance/medical_supplies.db
python app.py

๐Ÿ—บ๏ธ Frontend and Resource Types

{
  "value": "first_aid",
  "label": "First Aid Kit",
  "markerColor": "#FF0000",
  "badgeBackground": "#FFF",
  "badgeColor": "#000"
}

Restart the app after edits. Submissions are validated against these entries.


๐Ÿš€ Deployment

WSGI (Gunicorn)

gunicorn -c gunicorn_config.py app:app

Reverse Proxy & TLS

  • Place Gunicorn behind Nginx/Apache/Caddy.
  • Enforce HTTPS and caching.

Persistent Storage

  • Ensure instance/ is writable for SQLite.
  • For scaling, migrate to a managed RDBMS.

Environment

  • Provide secrets securely.
  • Rotate moderator credentials periodically.

๐Ÿ”’ Security Notes

  • Use strong moderator credentials.
  • Enable and store TOTP secrets securely.
  • CSP, X-Frame-Options, and similar headers are enforced.
  • Uploads restricted to PNG/JPEG โ‰ค16MB.
  • Votes are tokenized, not authenticated.

๐Ÿค Contributing

We welcome contributions that improve accessibility, data quality, and moderation UX.

  1. Open an issue for bugs or proposals.
  2. Fork โ†’ Branch โ†’ PR with clear description.
  3. Keep PRs focused and small.
  4. Include before/after screenshots for UI changes.
  5. Add tests where possible.

๐Ÿงญ Roadmap

  • Optional user accounts for trusted contributors
  • Map filters and search
  • Additional resource types and localization
  • Export/backup tooling
  • Rate-limiting and spam prevention
  • CI, tests, and coverage

๐Ÿ™ Acknowledgments

  • Map rendering by Mapbox.
  • Thanks to the open-source community for the Flask + mapping ecosystem.

๐Ÿ“„ License

This projectโ€™s license is TBD.
Add a LICENSE file (e.g., MIT/Apache-2.0) and update the badge when chosen.


๐Ÿ”— Project Meta

About

Crowdsourced information about first-aid kits, AEDS, and other emergency supplies.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published