Health, fitness, and wellness in open source form
  • HTML 53.2%
  • JavaScript 24.7%
  • Vue 21.7%
  • CSS 0.2%
  • Dockerfile 0.1%
  • Other 0.1%
Find a file
Brian McGonagill 52d5b0184e fix: resolve CVE vulnerabilities in backend and frontend dependencies
Security Audit & Remediation
=============================

Backend CVEs Fixed:
- nodemailer 8.x -> 9.0.3: Fixed CRLF injection (GHSA-268h-hp4c-crq3),
  jsonTransport bypass (GHSA-wqvq-jvpq-h66f), TLS cert validation bypass
  (GHSA-r7g4-qg5f-qqm2), raw option SSRF (GHSA-p6gq-j5cr-w38f)
- body-parser -> 1.20.6: Fixed DoS via invalid limit (GHSA-v422-hmwv-36x6)
- multer 2.1.x -> latest: Fixed DoS via nested fields (GHSA-72gw-mp4g-v24j)
  and incomplete cleanup (GHSA-3p4h-7m6x-2hcm)
- @babel/core -> 7.29.0+: Fixed arbitrary file read (GHSA-4x5r-pxfx-6jf8)
- form-data -> 4.0.6+: Fixed CRLF injection (GHSA-hmw2-7cc7-3qxx)
- js-yaml -> 4.x latest: Fixed quadratic DoS in merge keys (GHSA-h67p-54hq-rp68)
- brace-expansion -> 5.0.8 via override: Fixed DoS via unbounded expansion
  (GHSA-mh99-v99m-4gvg, GHSA-3jxr-9vmj-r5cp)
- jest 29.x -> 30.x (dev): Updated transitive dependency chain

Frontend CVEs Fixed:
- axios 1.15.x -> 1.17.x: Fixed 10 CVEs including prototype pollution
  (GHSA-xj6q-8x83-jv6g), DoS (GHSA-42h9-826w-cgv3, GHSA-pmv8-rq9r-6j72),
  SSRF bypass (GHSA-jqh4-m9w3-8hp9), proxy bypass (GHSA-f4gw-2p7v-4548)
- vite 8.0.x -> 8.1.x: Fixed NTLM hash disclosure (GHSA-v6wh-96g9-6wx3)
  and fs.deny bypass (GHSA-fx2h-pf6j-xcff)
- postcss -> 8.5.17+: Fixed path traversal via source maps (GHSA-r28c-9q8g-f849)
- undici -> 7.28.x: Fixed 7 CVEs including TLS bypass (GHSA-vmh5-mc38-953g),
  header injection (GHSA-p88m-4jfj-68fv), response queue poisoning
  (GHSA-35p6-xmwp-9g52)
- form-data -> 4.0.6+: Fixed CRLF injection (GHSA-hmw2-7cc7-3qxx)
- js-yaml -> 4.2.x: Fixed quadratic DoS (GHSA-h67p-54hq-rp68)
- brace-expansion -> 5.0.8 via override: Fixed DoS (GHSA-mh99-v99m-4gvg)
- cypress 14.x -> 15.x (dev): Fixed qs DoS via @cypress/request
  (GHSA-q8mj-m7cp-5q26)
- @playwright/test 1.58.x -> 1.62.x (dev)

Test Results:
- Backend: 6 test suites, 93 tests - ALL PASSED
- Frontend: 4 test files, 26 tests - ALL PASSED
- Frontend build: SUCCESS
- E2E: 15/77 passed (62 fail due to pre-existing test user seed data issue)
- Both npm audit: 0 vulnerabilities remaining
2026-07-25 20:45:12 -05:00
backend fix: resolve CVE vulnerabilities in backend and frontend dependencies 2026-07-25 20:45:12 -05:00
frontend fix: resolve CVE vulnerabilities in backend and frontend dependencies 2026-07-25 20:45:12 -05:00
.env.prod updates to fix tests and photo journal uploads. 2026-05-04 13:18:30 -05:00
.gitignore feat: core application structure with auth, routes, and calendar view 2026-03-27 19:37:23 -05:00
app_requirements.txt feat: add push notifications for workout reminders 2026-03-27 19:38:48 -05:00
CONTEXT.md add photo journal to track progress over time. 2026-04-05 12:05:58 -05:00
DEPLOYMENT.md Fix photo upload permission issues and add deployment docs 2026-05-04 13:17:37 -05:00
docker-compose.override.yml fix: configure Vite dev server proxy for Docker networking 2026-03-28 08:13:52 -05:00
docker-compose.prod.yml Fix Docker production images: remove nodemon, add OpenSSL 3.0.x support, create prod compose file 2026-05-02 12:51:44 -05:00
docker-compose.yml Updated to fix several issues with proxying, prod, and template seeding. 2026-05-05 19:28:27 -05:00
env.example compose updates 2026-05-02 08:53:58 -05:00
LICENSE Initial commit 2026-03-27 19:37:51 +00:00
nginx-upload-fix.conf updates to fix tests and photo journal uploads. 2026-05-04 13:18:30 -05:00
PRODUCTION_FIX.md Fix photo upload permission issues and add deployment docs 2026-05-04 13:17:37 -05:00
README.md Updated README 2026-04-05 12:55:14 -05:00
REVERSE_PROXY.md Fix photo upload permission issues and add deployment docs 2026-05-04 13:17:37 -05:00
SUMMARY.md Add comprehensive E2E tests for all features 2026-05-04 13:23:24 -05:00
TEST_RESULTS.md Add TEST_RESULTS.md with complete test results 2026-05-04 13:42:26 -05:00

Get Healthy

A clean, open-source fitness tracking application to help you track workouts, body measurements, and progress toward health goals.

Tech Stack

Layer Technology
Frontend Vue.js 3 + Vite + Tailwind CSS + Vue Router + Pinia
Backend Node.js + Express.js + Passport.js
Database PostgreSQL
ORM Prisma
Auth JWT (Local) + OIDC/OAuth2 (Google, GitHub, Keycloak, Authentik, Authelia)
API REST
Deployment Docker Compose

Features

Authentication

  • Email/password registration and login
  • OIDC/OAuth2 integration (Google, GitHub, Keycloak, Authentik, Authelia, Generic OIDC)
  • Password reset flow with SMTP email support
  • Email verification
  • First registered user automatically becomes admin

User Profile

  • Display name, avatar upload
  • Height, age, current weight tracking
  • Preferred weight unit (lb/kg)
  • Light/Dark mode with device detection
  • Push notification preferences
  • Full data deletion

Body Measurements

  • Weight, body fat percentage
  • Body measurements: waist, hips, chest, thighs, biceps, calves, shoulders, back span, neck
  • Historical tracking with interactive charts
  • Progress visualization over time

Workout Tracking

  • Create and manage workout routines
  • Routine types: Weightlifting, Aerobic, Flexibility, Combination
  • Exercise types: Strength, Cardio, Flexibility
  • Quick-entry UI for sets/reps/weight (mobile optimized)
  • RPE (Rate of Perceived Exertion) tracking
  • Continue previous incomplete workouts
  • Archive workouts individually or batch (by date range or name pattern)
  • View and restore archived workouts
  • Exercise name autocomplete from history

Workout Templates

  • Pre-built template library (StrongLifts, PPL, Couch to 5K, Starting Strength, 5K Training, HIIT, Yoga, Pilates, etc.)
  • Create custom templates with workout builder
  • Save workout as template
  • Browse/search templates by type, goal, difficulty

Photo Journal

  • Upload progress photos with categorization
  • Gallery view organized by category
  • Edit photo details (category, notes, date)
  • Timelapse playback for progress visualization
  • Full-screen photo viewer

Exercise Limits

  • Set upper/lower limits per exercise
  • Visual badges for limits in profile
  • Quick add/delete limits from profile

Scheduling

  • Schedule workouts on specific dates
  • Cadence system (every X days)
  • Calendar view
  • Push notification reminders (HTTPS required)

Reporting & Dashboard

  • Dashboard with summary charts
  • Progress tracking charts
  • Time-of-day analysis
  • Motivational messages
  • Calorie tracking

Admin

  • Admin dashboard
  • User management
  • System statistics
  • SMTP configuration and testing
  • OIDC provider configuration

AI Integration

  • Backend hooks for Ollama integration
  • Online AI support (OpenAI/Anthropic)

Data Management

  • JSON export
  • CSV export
  • Full data deletion

Getting Started

Prerequisites

  • Node.js 18+
  • Docker and Docker Compose

Quick Start (Docker)

# Clone the repository
git clone https://github.com/your-repo/get_healthy.git
cd get_healthy

# Start all services
docker-compose up -d

# Access the app
# Frontend: http://localhost:5173
# Backend API: http://localhost:3000

Development Setup

  1. Install dependencies:
# Backend
cd backend && npm install

# Frontend
cd ../frontend && npm install
  1. Start PostgreSQL with Docker:
docker-compose up -d db
  1. Set up the database:
cd backend
npx prisma db push
npx prisma generate
  1. Start the backend:
cd backend
npm run dev
  1. Start the frontend (in another terminal):
cd frontend
npm run dev
  1. Access the app:

Environment Variables

Backend (.env)

DATABASE_URL=postgresql://user:pass@localhost:5432/get_healthy
JWT_SECRET=your-secret-key
NODE_ENV=development
PORT=3000
FRONTEND_URL=http://localhost:5173

# OAuth / OIDC (optional - configure any combination)

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:3000/api/auth/oidc/google/callback

# GitHub OAuth
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_CALLBACK_URL=http://localhost:3000/api/auth/oidc/github/callback

# Keycloak OIDC
KEYCLOAK_CLIENT_ID=your-keycloak-client-id
KEYCLOAK_CLIENT_SECRET=your-keycloak-client-secret
KEYCLOAK_ISSUER=https://your-keycloak.com/realms/your-realm
KEYCLOAK_AUTHORIZATION_URL=https://your-keycloak.com/realms/your-realm/protocol/openid-connect/auth
KEYCLOAK_TOKEN_URL=https://your-keycloak.com/realms/your-realm/protocol/openid-connect/token
KEYCLOAK_USERINFO_URL=https://your-keycloak.com/realms/your-realm/protocol/openid-connect/userinfo
KEYCLOAK_CALLBACK_URL=http://localhost:3000/api/auth/oidc/keycloak/callback

# Authentik OIDC
AUTHENTIK_CLIENT_ID=your-authentik-client-id
AUTHENTIK_CLIENT_SECRET=your-authentik-client-secret
AUTHENTIK_ISSUER=https://your-authentik.com
AUTHENTIK_AUTHORIZATION_URL=https://your-authentik.com/application/o/authorize/
AUTHENTIK_TOKEN_URL=https://your-authentik.com/application/o/token/
AUTHENTIK_USERINFO_URL=https://your-authentik.com/application/o/userinfo/
AUTHENTIK_CALLBACK_URL=http://localhost:3000/api/auth/oidc/authentik/callback

# Authelia OIDC
AUTHELIA_CLIENT_ID=your-authelia-client-id
AUTHELIA_CLIENT_SECRET=your-authelia-client-secret
AUTHELIA_ISSUER=https://your-authelia.com
AUTHELIA_AUTHORIZATION_URL=https://your-authelia.com/api/oidc/authorization
AUTHELIA_TOKEN_URL=https://your-authelia.com/api/oidc/token
AUTHELIA_USERINFO_URL=https://your-authelia.com/api/oidc/userinfo
AUTHELIA_CALLBACK_URL=http://localhost:3000/api/auth/oidc/authelia/callback

# Generic OIDC Provider
OIDC_CLIENT_ID=your-oidc-client-id
OIDC_CLIENT_SECRET=your-oidc-client-secret
OIDC_ISSUER=https://your-idp.com
OIDC_AUTHORIZATION_URL=https://your-idp.com/authorize
OIDC_TOKEN_URL=https://your-idp.com/token
OIDC_USERINFO_URL=https://your-idp.com/userinfo
OIDC_CALLBACK_URL=http://localhost:3000/api/auth/oidc/generic/callback

# SMTP Configuration (optional - for password reset emails)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-smtp-user
SMTP_PASS=your-smtp-password
SMTP_FROM=your-from-email@example.com
SMTP_FROM_NAME=Get Healthy

Frontend (.env)

VITE_API_URL=http://localhost:3000/api

OIDC Setup

The application supports OAuth/OIDC authentication with both cloud providers (Google, GitHub) and self-hosted identity providers.

Supported Providers

Provider Type Protocol
Google Cloud OAuth 2.0
GitHub Cloud OAuth 2.0
Keycloak Self-hosted OIDC
Authentik Self-hosted OIDC
Authelia Self-hosted OIDC
Generic Self-hosted OIDC

Keycloak Setup

  1. Create a realm in Keycloak or use an existing one

  2. Create a client:

    • Client ID: get-healthy
    • Client Protocol: openid-connect
    • Access Type: confidential
    • Valid Redirect URIs: http://localhost:3000/api/auth/oidc/keycloak/callback
  3. Get credentials from the Credentials tab

  4. Get endpoints from: Realm Settings → Endpoints → OpenID Endpoint Configuration

  5. Set environment variables (see above)

Authentik Setup

  1. Create an OAuth2 Provider:

    • Name: Get Healthy
    • Client ID: get-healthy (auto-generated)
    • Redirect URIs: http://localhost:3000/api/auth/oidc/authentik/callback
  2. Create an Application linked to the provider

  3. Set environment variables (see above)

Generic OIDC Provider

For any OIDC-compliant provider, use the generic configuration with your provider's endpoints.

SMTP Setup

SMTP settings can also be configured from the Admin panel (Email tab):

  1. Navigate to Admin → Email
  2. Enter your SMTP credentials
  3. Click "Test Connection" to verify
  4. Save settings

Common SMTP Providers:

  • Gmail: smtp.gmail.com | Port 587 | Requires App Password
  • Outlook: smtp-mail.outlook.com | Port 587 | TLS
  • SendGrid: smtp.sendgrid.net | Port 587 | API Key
  • Mailgun: smtp.mailgun.org | Port 587 | TLS
  • AWS SES: email-smtp.us-east-1.amazonaws.com | Port 587 | SMTP credentials

Production Deployment

For production, update callback URLs to use your production domain:

FRONTEND_URL=https://get-healthy.example.com
GOOGLE_CALLBACK_URL=https://get-healthy.example.com/api/auth/oidc/google/callback
# etc.

Project Structure

/get_healthy
├── /frontend          # Vue.js SPA
│   ├── /src
│   │   ├── /components   # Reusable components (ConfirmModal, HelpIcon, etc.)
│   │   ├── /views        # Page components (Dashboard, Workout, etc.)
│   │   ├── /stores       # Pinia stores (auth, ui, notifications)
│   │   └── /router       # Vue Router config
│   └── ...
├── /backend           # Express.js API
│   ├── /src
│   │   ├── /routes       # API routes
│   │   ├── /controllers  # Route handlers
│   │   ├── /middleware   # Express middleware
│   │   └── /utils       # Utilities (passport-config, emailService, etc.)
│   └── /prisma          # Database schema
├── /docker            # Docker configs
├── docker-compose.yml
├── docker-compose.override.yml
└── README.md

API Endpoints

Auth

  • POST /api/auth/register - Register new user
  • POST /api/auth/login - Login
  • POST /api/auth/logout - Logout
  • GET /api/auth/me - Get current user
  • POST /api/password-reset/forgot - Request password reset
  • POST /api/password-reset/reset - Reset password with token
  • POST /api/email/verify - Verify email
  • POST /api/email/resend - Resend verification email
  • GET /api/auth/oidc/:provider - Initiate OIDC flow
  • GET /api/auth/oidc/:provider/callback - OIDC callback

Profile

  • GET /api/profile - Get user profile
  • PUT /api/profile - Update profile (displayName, height, age, weight, weightUnit)
  • POST /api/profile/avatar - Upload avatar
  • DELETE /api/profile - Delete all user data

Body Measurements

  • GET/POST /api/measurements - List/create measurements
  • GET /api/measurements/history - Measurement history
  • GET /api/measurements/latest - Latest measurement

Photo Journal

  • GET /api/photos - List all photos (optional ?category= filter)
  • GET /api/photos/categories - Get unique categories
  • GET /api/photos/category/:category - Get photos by category
  • GET /api/photos/:id - Get single photo
  • POST /api/photos - Upload photo (multipart/form-data)
  • PUT /api/photos/:id - Update photo (category, notes, takenAt)
  • DELETE /api/photos/:id - Delete photo

Routines

  • GET/POST /api/routines - List/create routines
  • GET/PUT/DELETE /api/routines/:id - Routine CRUD
  • GET /api/routines/:id - Get routine with workouts

Workouts

  • GET/POST /api/routines/:routineId/workouts - List/create workouts
  • GET/PUT/DELETE /api/routines/:routineId/workouts/:id - Workout CRUD
  • POST /api/routines/:routineId/workouts/:id/complete - Complete workout
  • POST /api/routines/:routineId/workouts/:id/archive - Archive workout
  • POST /api/routines/:routineId/workouts/:id/unarchive - Restore workout
  • GET /api/routines/:routineId/workouts/archived - Get archived workouts
  • POST /api/routines/:routineId/workouts/batch-archive - Batch archive by filter

Exercises

  • GET/POST /api/workouts/:workoutId/exercises - List/create exercises
  • PUT/DELETE /api/exercises/:id - Exercise CRUD

Sets & Logs

  • GET/POST /api/exercises/:exerciseId/sets - List/create sets
  • PUT/DELETE /api/sets/:id - Set CRUD
  • POST /api/exercises/:exerciseId/aerobic-log - Log aerobic data
  • PUT/DELETE /api/cardio-logs/:id - Cardio log CRUD
  • POST /api/exercises/:exerciseId/flexibility-log - Log flexibility data

Templates

  • GET/POST /api/templates - List/create templates
  • GET/PUT/DELETE /api/templates/:id - Template CRUD
  • GET /api/templates/public - Public templates
  • POST /api/templates/from-workout/:workoutId - Save workout as template
  • POST /api/templates/:id/start - Start workout from template

Exercise Limits

  • GET /api/limits - List all limits
  • GET /api/limits/exercise/:exerciseName - Get limits for exercise
  • POST /api/limits - Create/update limit
  • POST /api/limits/check - Check if value violates limit
  • DELETE /api/limits/:id - Delete limit

Schedule

  • GET/POST /api/schedule - List/create scheduled workouts
  • PUT/DELETE /api/schedule/:id - Schedule CRUD

Reports

  • GET /api/reports/progress - Progress data
  • GET /api/reports/calories - Calorie data
  • GET /api/reports/by-time-of-day - Time analysis
  • GET /api/reports/workout-frequency - Workout frequency
  • GET /api/reports/dashboard - Dashboard data

Dashboard

  • GET /api/dashboard - Dashboard data (alias for /api/reports/dashboard)

Export

  • GET /api/export/json - Export all data as JSON
  • GET /api/export/csv - Export measurements as CSV

Admin

  • GET /api/admin/users - List users
  • PUT/DELETE /api/admin/users/:id - Update/delete user
  • GET /api/admin/stats - System statistics
  • GET /api/admin/settings - Get admin settings
  • PUT /api/admin/settings/oidc - Update OIDC settings
  • PUT /api/admin/settings/smtp - Update SMTP settings
  • POST /api/admin/settings/smtp/test - Test SMTP connection

AI

  • POST /api/ai/analyze - Analyze workout with Ollama
  • GET /api/ai/health - Check Ollama connection

Scripts

# Backend
cd backend
npm run dev          # Development server
npm start           # Production server
npx prisma db push  # Push schema to database
npx prisma generate # Generate Prisma client
npx prisma studio   # Open Prisma Studio
npm test            # Run tests (88 tests passing)

# Frontend
cd frontend
npm run dev         # Development server (http://localhost:5173)
npm run build       # Production build
npm test            # Run tests (21 tests passing)
npm run test:e2e   # Run E2E tests
npm run lint        # Run ESLint

Database Schema

Core Entities

  • User - id, email, password_hash, role, provider, avatar, verification
  • UserProfile - user_id, display_name, height, age, weight, weight_unit, avatar_url
  • BodyMeasurement - weight, body fat, waist, hips, chest, thighs, biceps, calves, etc.
  • Routine - id, name, type (weightlifting/aerobic/flexibility/combination)
  • Workout - id, routine_id, name, scheduled_date, completed_at, archived
  • Exercise - id, workout_id, name, type (strength/cardio/flexibility)
  • ExerciseSet - id, exercise_id, set_number, reps, weight, rpe, completed
  • AerobicLog - duration, distance, heart_rate, calories, blood_pressure, spo2
  • FlexibilityLog - duration, notes

Template Entities

  • Template - id, name, description, type, goals[], difficulty, equipment[], is_public
  • TemplateWorkout - id, template_id, name, order
  • TemplateExercise - id, template_workout_id, name, type, default_sets, default_reps, rest_seconds

Scheduling Entities

  • ScheduledWorkout - id, user_id, routine_id, scheduled_date, cadence_type, cadence_value

Limits Entities

  • ExerciseLimit - id, user_id, exercise_name, limit_type (upper/lower), value, unit

Photo Journal Entities

  • Photo - id, user_id, filename, original_name, category, notes, taken_at, created_at

License

GPLv3