diff --git a/MEDICATION_MANAGEMENT_STATUS.md b/MEDICATION_MANAGEMENT_STATUS.md deleted file mode 100644 index e12493a..0000000 --- a/MEDICATION_MANAGEMENT_STATUS.md +++ /dev/null @@ -1,302 +0,0 @@ -# Medication Management System - Implementation Status - -## Phase 2.7 - Task 1 Status: COMPLETED โœ… - -Date: March 5, 2026 - ---- - -## What Was Accomplished - -### โœ… Core Implementation Complete - -The medication management system has been **successfully implemented** through a subagent delegation: - -**7 New API Endpoints Created:** -- `POST /api/medications` - Create medication -- `GET /api/medications` - List medications -- `GET /api/medications/:id` - Get medication details -- `PUT /api/medications/:id` - Update medication -- `DELETE /api/medications/:id` - Delete medication -- `POST /api/medications/:id/log` - Log dose -- `GET /api/medications/:id/adherence` - Calculate adherence - -### โœ… Features Implemented - -1. **Medication CRUD** - Full create, read, update, delete -2. **Dose Logging** - Track taken/skipped/missed doses -3. **Adherence Calculation** - Real-time adherence percentage -4. **Multi-Person Support** - Profile-based medication management -5. **Security** - JWT auth, user ownership validation, audit logging -6. **Error Handling** - Comprehensive error responses - -### โœ… Files Created/Modified - -**New Files:** -- `backend/src/handlers/medications.rs` - Medication endpoints -- `backend/src/models/medication_dose.rs` - Dose logging model - -**Modified Files:** -- `backend/src/handlers/mod.rs` - Added medication handler -- `backend/src/main.rs` - Added medication routes - ---- - -## Current Deployment Status - -### ๐ŸŸก Partially Deployed - -**Backend Status:** -- Code implemented: โœ… Yes -- Compiled successfully: โœ… Yes -- Git committed: โœ… Yes (commit pending) -- Deployed to Solaria: โณ TODO -- API tested: โณ TODO - -**Container Status:** -- Solaria backend: โœ… Running -- Solaria MongoDB: โœ… Running -- Port: 8001 (exposed) - ---- - -## Deployment & Testing Steps - -### Step 1: Commit Changes โœ… DONE -```bash -git add backend/src/handlers/medications.rs -git add backend/src/models/medication_dose.rs -git add backend/src/handlers/mod.rs -git add backend/src/main.rs -git commit -m "feat(backend): Implement Phase 2.7 Task 1 - Medication Management System" -``` - -### Step 2: Push to Remote -```bash -git push origin main -``` - -### Step 3: Rebuild on Solaria -```bash -ssh solaria 'cd /srv/normogen && git pull && docker compose build && docker compose up -d' -``` - -### Step 4: Test the API -```bash -# Health check -curl http://solaria.solivarez.com.ar:8001/health - -# Create test user -curl -X POST http://solaria.solivarez.com.ar:8001/api/auth/register \ - -H "Content-Type: application/json" \ - -d '{"email":"med-test@example.com","username":"medtest","password":"SecurePass123!","first_name":"Test","last_name":"User"}' - -# Login -curl -X POST http://solaria.solivarez.com.ar:8001/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"med-test@example.com","password":"SecurePass123!"}' - -# Create medication (use token from login) -curl -X POST http://solaria.solivarez.com.ar:8001/api/medications \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer YOUR_TOKEN" \ - -d '{"medication_name":"Lisinopril","dosage":"10mg","frequency":"once_daily"}' - -# List medications -curl http://solaria.solivarez.com.ar:8001/api/medications \ - -H "Authorization: Bearer YOUR_TOKEN" -``` - ---- - -## Test Results - -### Expected Results: -- โœ… All endpoints should return HTTP 200-201 -- โœ… Adherence calculation should work -- โœ… Multi-person profiles should work -- โœ… Security/authorization should be enforced - -### Test Checklist: -- [ ] Health check returns 200 -- [ ] User registration works -- [ ] Login returns JWT token -- [ ] Can create medication -- [ ] Can list medications -- [ ] Can update medication -- [ ] Can delete medication -- [ ] Can log dose -- [ ] Adherence calculation works - ---- - -## Next Steps - -### Immediate (After Testing) -1. โœ… Deploy to Solaria -2. โœ… Run comprehensive API tests -3. โœ… Verify all endpoints work correctly -4. โœ… Document any issues found - -### Phase 2.7 Continuation -**Task 2: Health Statistics** (Next Priority) -- Weight, BP, heart rate tracking -- Trend analysis -- Similar pattern to medications -- Estimated: 3 days (with AI: ~15 minutes) - -**Task 3: Profile Management** -- Multi-person profile CRUD -- Family member management -- Profile switching -- Estimated: 1 day - -**Task 4: Basic Health Sharing** -- Share medications with family -- Expiring links -- Read-only access -- Estimated: 3 days - -**Task 5: Notification System** -- Medication reminders -- Missed dose alerts -- In-app notifications -- Estimated: 4 days - ---- - -## Implementation Quality - -### โœ… Production Ready -- Clean code following existing patterns -- Proper error handling -- Security best practices implemented -- Comprehensive CRUD operations -- Multi-person support -- Audit logging integrated - -### ๐Ÿ“Š Code Metrics -- New endpoints: 7 -- Lines of code: ~400 -- Test coverage: To be added -- Documentation: Included in code -- Performance: Optimized with proper indexes - ---- - -## Architecture - -``` -Request โ†’ JWT Auth โ†’ Handler โ†’ Repository โ†’ MongoDB - โ†“ - Audit Logger - โ†“ - Response -``` - -### Security Flow: -1. Request arrives with JWT token -2. Auth middleware validates token -3. Handler checks user/profile ownership -4. Operation performed in MongoDB -5. Audit log entry created -6. Response returned to client - ---- - -## MVP Impact - -### โœ… Critical Value Delivered - -This is a **core MVP feature** for Normogen: - -**Problem Solved:** -- ๐Ÿ’Š $500B+ medication adherence problem -- ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง Families struggle to manage meds together -- ๐Ÿ”’ Privacy concerns with health apps - -**Solution Provided:** -- Multi-person medication tracking -- Real-time adherence monitoring -- Privacy-first design -- Family collaboration - -**User Value:** -- Never miss a dose -- Track entire family's medications -- Improve health outcomes -- Peace of mind - ---- - -## Files Reference - -### Handler Implementation -**File:** `backend/src/handlers/medications.rs` - -Key functions: -- `create_medication` - Create new medication -- `list_medications` - List all user's medications -- `get_medication` - Get specific medication -- `update_medication` - Update medication details -- `delete_medication` - Delete medication -- `log_dose` - Log dose taken/skipped/missed -- `calculate_adherence` - Calculate adherence % - -### Model -**File:** `backend/src/models/medication.rs` - -Fields: -- medication_name -- dosage -- frequency -- instructions -- start_date -- end_date -- profile_id (for multi-person) -- user_id (owner) - -### Dose Model -**File:** `backend/src/models/medication_dose.rs` - -Fields: -- medication_id -- status (taken/skipped/missed) -- logged_at -- notes -- user_id - ---- - -## Deployment Status Summary - -| Component | Status | Notes | -|-----------|--------|-------| -| Code Implementation | โœ… Complete | All endpoints implemented | -| Compilation | โœ… Successful | No errors | -| Git Commit | โœ… Ready | Pending push | -| Solaria Build | โณ TODO | Need to rebuild container | -| API Testing | โณ TODO | Need to run tests | -| Documentation | โœ… Complete | This document | - ---- - -## Conclusion - -**Task 1 Status: COMPLETE โœ…** - -The medication management system is **fully implemented and ready for deployment**. This is a critical MVP feature that delivers real value to users. - -**Estimated time to complete remaining steps:** 30 minutes -- Push to Solaria: 5 min -- Rebuild container: 10 min -- Run tests: 10 min -- Document results: 5 min - -**Ready for Task 2 (Health Statistics) after testing complete.** - ---- - -*Generated: March 5, 2026* -*Phase: 2.7 - Task 1 of 5* -*Progress: 20% complete* diff --git a/PHASE_2.7_DEPLOYMENT_PLAN.md b/PHASE_2.7_DEPLOYMENT_PLAN.md deleted file mode 100644 index aa68f8d..0000000 --- a/PHASE_2.7_DEPLOYMENT_PLAN.md +++ /dev/null @@ -1,378 +0,0 @@ -# ๐ŸŽฏ Phase 2.7 MVP - Project Analysis & Deployment Plan - -**Date:** March 7, 2026 -**Current Phase:** 2.7 - MVP Health Features -**Status:** ๐ŸŸก Partially Complete - Ready for Deployment - ---- - -## ๐Ÿ“Š Current State Analysis - -### โœ… What's Already Implemented - -#### 1. Core Infrastructure (COMPLETE) -- **Backend Framework:** Rust with Axum web framework -- **Database:** MongoDB with proper indexing -- **Authentication:** JWT-based auth system -- **Security:** Phase 2.6 security hardening complete - - Session management - - Audit logging - - Account lockout - - Security headers - - Rate limiting middleware - -#### 2. Authentication & User Management (COMPLETE) -- User registration and login -- Profile management -- Password recovery -- Settings management -- Session tracking - -#### 3. Data Sharing (COMPLETE) -- Create/list/update/delete shares -- Permission checking -- Resource-based access control - -#### 4. Medication Management (IMPLEMENTED - NEEDS TESTING) -**Status:** Code implemented, not yet deployed to Solaria - -**7 Endpoints Created:** -- `POST /api/medications` - Create medication -- `GET /api/medications` - List all user's medications -- `GET /api/medications/:id` - Get specific medication -- `PUT /api/medications/:id` - Update medication -- `DELETE /api/medications/:id` - Delete medication -- `POST /api/medications/:id/log` - Log dose taken/skipped -- `GET /api/medications/:id/adherence` - Calculate adherence % - -**Features:** -- Multi-person support (profile_id) -- Encrypted medication data -- Dose logging with timestamps -- Adherence calculation (30-day window) -- User ownership validation -- Audit logging integration - ---- - -## ๐Ÿ“‹ MVP Requirements vs Current Status - -### MVP Critical Features (from PHASE_2.7_MVP_PRIORITIZED_PLAN.md) - -| Feature | Priority | Status | Notes | -|---------|----------|--------|-------| -| **Medication Tracking** | ๐Ÿ”ด CRITICAL | ๐ŸŸก Implemented | Code complete, needs deployment & testing | -| **Health Statistics** | ๐Ÿ”ด CRITICAL | โšช Not Started | Need to implement | -| **Profile Management** | ๐Ÿ”ด CRITICAL | ๐ŸŸก Partial | Basic profile exists, needs family profiles | -| **Simple Reminders** | ๐Ÿ”ด CRITICAL | โšช Not Started | Need notification system | -| **Basic Sharing** | ๐Ÿ”ด IMPORTANT | โœ… Complete | Already implemented | - ---- - -## ๐Ÿš€ Deployment Plan - -### Current Deployment Status - -**Solaria Server:** -- Backend Container: ๐ŸŸข Running on port 8001 -- MongoDB Container: ๐ŸŸข Running -- Last Deployment: Phase 2.6 (Security Hardening) -- Last Test: March 5, 2026 - All tests passed (16/16) - -**Git Status:** -- Latest commit: `6e7ce4d` - "feat(backend): Implement Phase 2.7 Task 1 - Medication Management System" -- Untracked files: Test scripts for medication endpoints - -### Immediate Deployment Steps - -#### Step 1: Commit & Push Changes -```bash -# Add medication management files -git add backend/src/handlers/medications.rs -git add backend/src/models/medication_dose.rs -git add backend/src/handlers/mod.rs -git add backend/src/main.rs -git add backend/src/db/mod.rs # If updated - -# Add test scripts -git add test-medication-api.sh -git add backend/test-medication-endpoints.sh - -# Commit -git commit -m "feat(backend): Add medication management and test scripts - -- Implement medication CRUD operations -- Add dose logging and adherence tracking -- Support multi-person profiles -- Add comprehensive test scripts -- Phase 2.7 Task 1 complete" - -# Push -git push origin main -``` - -#### Step 2: Deploy to Solaria -```bash -# Use existing deployment script -./deploy-to-solaria.sh -``` - -**This will:** -1. Push latest changes to git -2. SSH to Solaria -3. Pull latest code -4. Rebuild Docker container -5. Restart services -6. Show logs - -#### Step 3: Verify Deployment -```bash -# Check container status -ssh alvaro@solaria 'docker ps | grep normogen' - -# Check health endpoint -curl http://solaria.solivarez.com.ar:8001/health - -# Check logs -ssh alvaro@solaria 'docker logs normogen-backend | tail -50' -``` - -#### Step 4: Test All Endpoints -```bash -# Run comprehensive test -./test-api-endpoints.sh - -# Run medication-specific tests -./test-medication-api.sh -``` - ---- - -## ๐Ÿงช Testing Strategy - -### Test Categories - -#### 1. Health Check Tests -- [ ] GET /health returns 200 -- [ ] GET /ready returns 200 - -#### 2. Authentication Tests -- [ ] POST /api/auth/register creates new user -- [ ] POST /api/auth/login returns JWT token -- [ ] Invalid login returns 401 - -#### 3. Medication Management Tests (NEW) -- [ ] Create medication with valid data -- [ ] Create medication fails with invalid data -- [ ] List medications returns empty array initially -- [ ] List medications returns created medications -- [ ] Get specific medication by ID -- [ ] Get medication fails for non-existent ID -- [ ] Update medication -- [ ] Update medication owned by different user fails (403) -- [ ] Delete medication -- [ ] Delete medication owned by different user fails (403) - -#### 4. Dose Logging Tests (NEW) -- [ ] Log dose as taken -- [ ] Log dose as skipped -- [ ] Log dose for non-existent medication fails -- [ ] Adherence calculation returns correct percentage - -#### 5. Authorization Tests -- [ ] All protected endpoints return 401 without token -- [ ] Invalid token returns 401 -- [ ] Expired token returns 401 - -#### 6. Security Tests -- [ ] SQL injection attempts fail -- [ ] XSS attempts are sanitized -- [ ] Rate limiting works -- [ ] Security headers are present - ---- - -## ๐Ÿ“ Remaining MVP Work - -### After Successful Medication Deployment - -#### Task 2: Health Statistics (3 days) -**Endpoints to Create:** -```rust -// backend/src/handlers/health_stats.rs -- POST /api/health-stats // Add health stat -- GET /api/health-stats // List stats -- GET /api/health-stats/trend/:type // Get trend -- DELETE /api/health-stats/:id // Delete stat -``` - -**Metrics to Track:** -- Weight -- Blood Pressure (systolic/diastolic) -- Heart Rate -- Temperature -- Blood Glucose -- Custom metrics - -#### Task 3: Profile Management (1 day) -**Enhancements Needed:** -- Multi-person profile CRUD -- Family member management -- Profile switching -- Profile-based data filtering - -#### Task 4: Notification System (4 days) -**Endpoints to Create:** -```rust -// backend/src/handlers/notifications.rs -- POST /api/notifications // Create notification -- GET /api/notifications // List notifications -- PUT /api/notifications/:id/read // Mark as read -- DELETE /api/notifications/:id // Delete notification -``` - -**Notification Types:** -- Medication reminders -- Missed dose alerts -- Sharing invites -- Health alerts - ---- - -## ๐ŸŽฏ Success Criteria - -### For This Deployment Session -- [ ] Medication code deployed to Solaria -- [ ] All 7 medication endpoints tested -- [ ] All tests pass (100% success rate) -- [ ] No compilation errors -- [ ] No runtime errors -- [ ] Documentation updated - -### For MVP Completion (Phase 2.7) -- [ ] Medication tracking operational -- [ ] Health statistics operational -- [ ] Multi-person profiles operational -- [ ] Basic notifications operational -- [ ] All features tested end-to-end -- [ ] Performance meets requirements (<500ms p95) -- [ ] Security audit passed - ---- - -## ๐Ÿ”’ Security Considerations - -### Already Implemented -- โœ… JWT authentication -- โœ… User ownership validation -- โœ… Audit logging -- โœ… Security headers -- โœ… Rate limiting -- โœ… Input validation -- โœ… Error sanitization - -### For New Features -- Profile data isolation (user can only access their profiles) -- Health data access logging -- Notification content sanitization (no sensitive data) - ---- - -## ๐Ÿ“Š API Documentation - -### Medication Endpoints - -#### Create Medication -```bash -curl -X POST http://solaria.solivarez.com.ar:8001/api/medications \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer YOUR_TOKEN" \ - -d '{ - "profile_id": "profile-id-or-null", - "name": "Lisinopril", - "dosage": "10mg", - "frequency": "once_daily", - "instructions": "Take with breakfast", - "start_date": "2026-03-01", - "reminders": [ - { - "time": "08:00", - "days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] - } - ] - }' -``` - -#### List Medications -```bash -curl http://solaria.solivarez.com.ar:8001/api/medications \ - -H "Authorization: Bearer YOUR_TOKEN" -``` - -#### Log Dose -```bash -curl -X POST http://solaria.solivarez.com.ar:8001/api/medications/{MED_ID}/log \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer YOUR_TOKEN" \ - -d '{ - "taken": true, - "scheduled_time": "2026-03-07T08:00:00Z", - "notes": "Taken with breakfast" - }' -``` - -#### Get Adherence -```bash -curl http://solaria.solivarez.com.ar:8001/api/medications/{MED_ID}/adherence \ - -H "Authorization: Bearer YOUR_TOKEN" -``` - -**Response:** -```json -{ - "total_doses": 30, - "taken_doses": 27, - "missed_doses": 3, - "adherence_percentage": 90.0 -} -``` - ---- - -## ๐Ÿšฆ Next Steps - -### Immediate (Today) -1. โœ… Analyze current state (DONE) -2. โณ Commit medication changes -3. โณ Deploy to Solaria -4. โณ Run comprehensive tests -5. โณ Document results - -### This Week -1. Deploy medication management -2. Implement health statistics -3. Enhance profile management - -### Next Week -1. Build notification system -2. Integration testing -3. Performance optimization - ---- - -## ๐Ÿ“Œ Summary - -**Current Status:** Phase 2.7 Medication Management is implemented but not deployed - -**What Needs to Happen:** -1. Commit the medication code (already written) -2. Push to git -3. Deploy to Solaria (automated script exists) -4. Test all endpoints (test scripts exist) -5. Document results - -**Estimated Time:** 30-45 minutes - -**After This:** Continue with Task 2 (Health Statistics) - -**MVP Completion:** Estimated 2-3 weeks total (currently ~20% complete) diff --git a/PHASE_2.7_PROGRESS_SUMMARY.md b/PHASE_2.7_PROGRESS_SUMMARY.md deleted file mode 100644 index 889b89d..0000000 --- a/PHASE_2.7_PROGRESS_SUMMARY.md +++ /dev/null @@ -1,42 +0,0 @@ -# Phase 2.7 MVP - Progress Summary - -**Date:** 2026-03-07 16:24 -**Status:** ๐ŸŸก IN PROGRESS (1 Complete, 1 In Progress, 3 Pending) - ---- - -## โœ… COMPLETED TASKS - -### Task 1: Medication Management System (100% Complete) -**Status:** โœ… DEPLOYED & TESTED ON SOLARIA - -All 7 API endpoints fully functional with 100% test pass rate. - ---- - -## ๐ŸŸก IN PROGRESS TASKS - -### Task 2: Health Statistics Tracking (60% Complete) -**Status:** ๐ŸŸก CODE WRITTEN, COMPILATION ERRORS REMAINING - -Model, repository, and handlers created but need fixes. - ---- - -## ๐Ÿ“Š OVERALL PROGRESS - -**Overall: 1/5 tasks complete (20%)** -**With in-progress: 1.6/5 tasks (32%)** - ---- - -## ๐ŸŽฏ IMMEDIATE NEXT STEPS - -1. Fix health stats compilation errors -2. Deploy to Solaria -3. Implement Profile Management -4. Implement Notification System - ---- - -**Last Updated:** March 7, 2026 @ 16:24 UTC diff --git a/backend/deploy-and-test.sh b/backend/deploy-and-test.sh deleted file mode 100755 index 7ed248d..0000000 --- a/backend/deploy-and-test.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -echo "==========================================" -echo "Normogen Deployment & Testing Script" -echo "==========================================" -echo "" - -# Step 1: Push to remote -echo "Step 1: Pushing to remote..." -git push origin main -if [ $? -ne 0 ]; then - echo "โœ— Git push failed" - exit 1 -fi -echo "โœ“ Git push successful" -echo "" - -# Step 2: Connect to Solaria and update -echo "Step 2: Updating Solaria..." -ssh solaria 'cd /srv/normogen && git pull' -if [ $? -ne 0 ]; then - echo "โœ— Git pull on Solaria failed" - exit 1 -fi -echo "โœ“ Code updated on Solaria" -echo "" - -# Step 3: Build new container -echo "Step 3: Building Docker container..." -ssh solaria 'cd /srv/normogen && docker compose -f docker/docker-compose.improved.yml build backend' -if [ $? -ne 0 ]; then - echo "โœ— Docker build failed" - exit 1 -fi -echo "โœ“ Docker build successful" -echo "" - -# Step 4: Restart containers -echo "Step 4: Restarting containers..." -ssh solaria 'cd /srv/normogen && docker compose -f docker/docker-compose.improved.yml down && docker compose -f docker/docker-compose.improved.yml up -d' -if [ $? -ne 0 ]; then - echo "โœ— Container restart failed" - exit 1 -fi -echo "โœ“ Containers restarted" -echo "" - -# Step 5: Wait for container to be healthy -echo "Step 5: Waiting for backend to be healthy..." -sleep 10 -ssh solaria 'docker ps | grep normogen' -echo "" - -# Step 6: Run API tests -echo "Step 6: Running API tests..." -chmod +x test-medication-endpoints.sh -./test-medication-endpoints.sh -echo "" - -echo "==========================================" -echo "Deployment & Testing Complete" -echo "==========================================" diff --git a/backend/src/config/mod.rs b/backend/src/config/mod.rs index a850b9b..74196dd 100644 --- a/backend/src/config/mod.rs +++ b/backend/src/config/mod.rs @@ -10,8 +10,6 @@ pub struct AppState { pub audit_logger: Option, pub session_manager: Option, pub account_lockout: Option, - pub health_stats_repo: Option, - pub mongo_client: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/backend/src/handlers/health_stats.rs b/backend/src/handlers/health_stats.rs deleted file mode 100644 index a6ee583..0000000 --- a/backend/src/handlers/health_stats.rs +++ /dev/null @@ -1,267 +0,0 @@ -use axum::{ - extract::{Path, Query, State}, - http::StatusCode, - Json, -}; -use mongodb::bson::oid::ObjectId; -use serde::{Deserialize, Serialize}; - -use crate::models::health_stats::{ - CreateHealthStatRequest, HealthStatistic, HealthStatType, HealthStatValue, - HealthStatisticsRepository, UpdateHealthStatRequest, -}; -use crate::auth::jwt::Claims; - -#[derive(Debug, Deserialize)] -pub struct ListStatsQuery { - pub stat_type: Option, - pub profile_id: Option, - pub limit: Option, -} - -#[derive(Debug, Deserialize)] -pub struct TrendQuery { - pub profile_id: String, - pub stat_type: String, - pub days: Option, -} - -#[derive(Debug, Serialize)] -pub struct TrendResponse { - pub stat_type: String, - pub profile_id: String, - pub days: i64, - pub data_points: i64, - pub stats: Vec, - pub summary: TrendSummary, -} - -#[derive(Debug, Serialize)] -pub struct TrendSummary { - pub latest: Option, - pub earliest: Option, - pub average: Option, - pub min: Option, - pub max: Option, - pub trend: String, -} - -pub async fn create_health_stat( - State(repo): State, - claims: Claims, - Json(req): Json, -) -> Result, StatusCode> { - let stat_type = parse_stat_type(&req.stat_type); - let value = parse_stat_value(&req.value, &stat_type); - let unit = req.unit.unwrap_or_else(|| stat_type.default_unit().to_string()); - - let now = mongodb::bson::DateTime::now(); - let health_stat_id = uuid::Uuid::new_v4().to_string(); - - let stat = HealthStatistic { - id: None, - health_stat_id, - user_id: claims.user_id.clone(), - profile_id: req.profile_id.clone(), - stat_type, - value, - unit, - recorded_at: req.recorded_at.unwrap_or(now), - notes: req.notes, - tags: req.tags.unwrap_or_default(), - created_at: now, - updated_at: now, - }; - - match repo.create(stat.clone()).await { - Ok(created) => Ok(Json(created)), - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - } -} - -pub async fn list_health_stats( - State(repo): State, - claims: Claims, - Query(query): Query, -) -> Result>, StatusCode> { - let limit = query.limit.unwrap_or(100); - - match repo - .list_by_user( - &claims.user_id, - query.stat_type.as_deref(), - query.profile_id.as_deref(), - limit, - ) - .await - { - Ok(stats) => Ok(Json(stats)), - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - } -} - -pub async fn get_health_stat( - State(repo): State, - claims: Claims, - Path(id): Path, -) -> Result, StatusCode> { - match ObjectId::parse_str(&id) { - Ok(oid) => match repo.get_by_id(&oid, &claims.user_id).await { - Ok(Some(stat)) => Ok(Json(stat)), - Ok(None) => Err(StatusCode::NOT_FOUND), - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - }, - Err(_) => Err(StatusCode::BAD_REQUEST), - } -} - -pub async fn update_health_stat( - State(repo): State, - claims: Claims, - Path(id): Path, - Json(req): Json, -) -> Result, StatusCode> { - match ObjectId::parse_str(&id) { - Ok(oid) => match repo.update(&oid, &claims.user_id, req).await { - Ok(Some(stat)) => Ok(Json(stat)), - Ok(None) => Err(StatusCode::NOT_FOUND), - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - }, - Err(_) => Err(StatusCode::BAD_REQUEST), - } -} - -pub async fn delete_health_stat( - State(repo): State, - claims: Claims, - Path(id): Path, -) -> Result { - match ObjectId::parse_str(&id) { - Ok(oid) => match repo.delete(&oid, &claims.user_id).await { - Ok(true) => Ok(StatusCode::NO_CONTENT), - Ok(false) => Err(StatusCode::NOT_FOUND), - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - }, - Err(_) => Err(StatusCode::BAD_REQUEST), - } -} - -pub async fn get_health_trends( - State(repo): State, - claims: Claims, - Query(query): Query, -) -> Result, StatusCode> { - let days = query.days.unwrap_or(30); - - match repo - .get_trends(&claims.user_id, &query.profile_id, &query.stat_type, days) - .await - { - Ok(stats) => { - let data_points = stats.len() as i64; - let summary = calculate_summary(&stats); - - let response = TrendResponse { - stat_type: query.stat_type.clone(), - profile_id: query.profile_id, - days, - data_points, - stats, - summary, - }; - - Ok(Json(response)) - } - Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), - } -} - -fn parse_stat_type(stat_type: &str) -> HealthStatType { - match stat_type.to_lowercase().as_str() { - "weight" => HealthStatType::Weight, - "height" => HealthStatType::Height, - "blood_pressure" => HealthStatType::BloodPressure, - "heart_rate" => HealthStatType::HeartRate, - "temperature" => HealthStatType::Temperature, - "blood_glucose" => HealthStatType::BloodGlucose, - "oxygen_saturation" => HealthStatType::OxygenSaturation, - "sleep_hours" => HealthStatType::SleepHours, - "steps" => HealthStatType::Steps, - "calories" => HealthStatType::Calories, - custom => HealthStatType::Custom(custom.to_string()), - } -} - -fn parse_stat_value(value: &serde_json::Value, stat_type: &HealthStatType) -> HealthStatValue { - match stat_type { - HealthStatType::BloodPressure => { - if let Some(obj) = value.as_object() { - let systolic = obj.get("systolic").and_then(|v| v.as_f64()).unwrap_or(0.0); - let diastolic = obj.get("diastolic").and_then(|v| v.as_f64()).unwrap_or(0.0); - HealthStatValue::BloodPressure { systolic, diastolic } - } else { - HealthStatValue::Single(0.0) - } - } - _ => { - if let Some(num) = value.as_f64() { - HealthStatValue::Single(num) - } else if let Some(str_val) = value.as_str() { - HealthStatValue::String(str_val.to_string()) - } else { - HealthStatValue::Single(0.0) - } - } - } -} - -fn calculate_summary(stats: &[HealthStatistic]) -> TrendSummary { - let mut values: Vec = Vec::new(); - - for stat in stats { - match &stat.value { - HealthStatValue::Single(v) => values.push(*v), - HealthStatValue::BloodPressure { systolic, .. } => values.push(*systolic), - _ => {} - } - } - - if values.is_empty() { - return TrendSummary { - latest: None, - earliest: None, - average: None, - min: None, - max: None, - trend: "stable".to_string(), - }; - } - - let latest = values.last().copied(); - let earliest = values.first().copied(); - let average = values.iter().sum::() / values.len() as f64; - let min = values.iter().fold(f64::INFINITY, |a, &b| a.min(b)); - let max = values.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b)); - - let trend = if let (Some(l), Some(e)) = (latest, earliest) { - let change = ((l - e) / e * 100.0).abs(); - if l > e && change > 5.0 { - "up" - } else if l < e && change > 5.0 { - "down" - } else { - "stable" - } - } else { - "stable" - }; - - TrendSummary { - latest, - earliest, - average: Some(average), - min: Some(min), - max: Some(max), - trend: trend.to_string(), - } -} diff --git a/backend/src/handlers/mod.rs b/backend/src/handlers/mod.rs index 761843d..c67a580 100644 --- a/backend/src/handlers/mod.rs +++ b/backend/src/handlers/mod.rs @@ -1,6 +1,5 @@ pub mod auth; pub mod health; -pub mod health_stats; pub mod permissions; pub mod shares; pub mod users; @@ -15,4 +14,3 @@ pub use permissions::check_permission; pub use users::{get_profile, update_profile, delete_account, change_password, get_settings, update_settings}; pub use sessions::{get_sessions, revoke_session, revoke_all_sessions}; pub use medications::{create_medication, list_medications, get_medication, update_medication, delete_medication, log_dose, get_adherence}; -pub use health_stats::{create_health_stat, list_health_stats, get_health_stat, update_health_stat, delete_health_stat, get_health_trends}; diff --git a/backend/src/main.rs b/backend/src/main.rs index 6b8711c..fc92327 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -78,7 +78,6 @@ async fn main() -> anyhow::Result<()> { // Get the underlying MongoDB database for security services let database = db.get_database(); - let mongo_client = database.client().clone(); // Initialize security services (Phase 2.6) let audit_logger = security::AuditLogger::new(&database); @@ -93,12 +92,6 @@ async fn main() -> anyhow::Result<()> { 1440, // max_duration_minutes (24 hours) ); - // Initialize health stats repository (Phase 2.7) - using Collection pattern - let health_stats_collection = database.collection("health_statistics"); - let health_stats_repo = models::health_stats::HealthStatisticsRepository::new( - health_stats_collection - ); - // Create application state let state = config::AppState { db, @@ -107,10 +100,8 @@ async fn main() -> anyhow::Result<()> { audit_logger: Some(audit_logger), session_manager: Some(session_manager), account_lockout: Some(account_lockout), - health_stats_repo: Some(health_stats_repo), - mongo_client: Some(mongo_client), }; - + eprintln!("Building router with security middleware..."); // Build public routes (no auth required) @@ -155,14 +146,6 @@ async fn main() -> anyhow::Result<()> { .route("/api/medications/:id/delete", post(handlers::delete_medication)) .route("/api/medications/:id/log", post(handlers::log_dose)) .route("/api/medications/:id/adherence", get(handlers::get_adherence)) - - // Health statistics management (Phase 2.7) - .route("/api/health-stats", post(handlers::create_health_stat)) - .route("/api/health-stats", get(handlers::list_health_stats)) - .route("/api/health-stats/trends", get(handlers::get_health_trends)) - .route("/api/health-stats/:id", get(handlers::get_health_stat)) - .route("/api/health-stats/:id", put(handlers::update_health_stat)) - .route("/api/health-stats/:id", delete(handlers::delete_health_stat)) .layer(axum::middleware::from_fn_with_state( state.clone(), middleware::jwt_auth_middleware diff --git a/backend/src/models/health_stats.rs b/backend/src/models/health_stats.rs deleted file mode 100644 index 31eab4e..0000000 --- a/backend/src/models/health_stats.rs +++ /dev/null @@ -1,246 +0,0 @@ -use serde::{Deserialize, Serialize}; -use mongodb::{bson::{oid::ObjectId, doc}, Collection, DateTime}; -use futures::stream::TryStreamExt; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct HealthStatistic { - #[serde(rename = "_id", skip_serializing_if = "Option::is_none")] - pub id: Option, - #[serde(rename = "healthStatId")] - pub health_stat_id: String, - #[serde(rename = "userId")] - pub user_id: String, - #[serde(rename = "profileId")] - pub profile_id: String, - #[serde(rename = "statType")] - pub stat_type: HealthStatType, - #[serde(rename = "value")] - pub value: HealthStatValue, - #[serde(rename = "unit")] - pub unit: String, - #[serde(rename = "recordedAt")] - pub recorded_at: DateTime, - #[serde(rename = "notes")] - pub notes: Option, - #[serde(rename = "tags")] - pub tags: Vec, - #[serde(rename = "createdAt")] - pub created_at: DateTime, - #[serde(rename = "updatedAt")] - pub updated_at: DateTime, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -pub enum HealthStatType { - Weight, - Height, - BloodPressure, - HeartRate, - Temperature, - BloodGlucose, - OxygenSaturation, - SleepHours, - Steps, - Calories, - Custom(String), -} - -impl HealthStatType { - pub fn as_str(&self) -> &str { - match self { - HealthStatType::Weight => "weight", - HealthStatType::Height => "height", - HealthStatType::BloodPressure => "blood_pressure", - HealthStatType::HeartRate => "heart_rate", - HealthStatType::Temperature => "temperature", - HealthStatType::BloodGlucose => "blood_glucose", - HealthStatType::OxygenSaturation => "oxygen_saturation", - HealthStatType::SleepHours => "sleep_hours", - HealthStatType::Steps => "steps", - HealthStatType::Calories => "calories", - HealthStatType::Custom(name) => name, - } - } - - pub fn default_unit(&self) -> &str { - match self { - HealthStatType::Weight => "kg", - HealthStatType::Height => "cm", - HealthStatType::BloodPressure => "mmHg", - HealthStatType::HeartRate => "bpm", - HealthStatType::Temperature => "ยฐC", - HealthStatType::BloodGlucose => "mg/dL", - HealthStatType::OxygenSaturation => "%", - HealthStatType::SleepHours => "hours", - HealthStatType::Steps => "steps", - HealthStatType::Calories => "kcal", - HealthStatType::Custom(_) => "", - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum HealthStatValue { - Single(f64), - BloodPressure { systolic: f64, diastolic: f64 }, - String(String), -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CreateHealthStatRequest { - pub profile_id: String, - #[serde(rename = "statType")] - pub stat_type: String, - pub value: serde_json::Value, - pub unit: Option, - #[serde(rename = "recordedAt")] - pub recorded_at: Option, - pub notes: Option, - pub tags: Option>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct UpdateHealthStatRequest { - pub value: Option, - pub unit: Option, - #[serde(rename = "recordedAt")] - pub recorded_at: Option, - pub notes: Option, - pub tags: Option>, -} - -#[derive(Clone)] -pub struct HealthStatisticsRepository { - pub collection: Collection, -} - -impl HealthStatisticsRepository { - pub fn new(collection: Collection) -> Self { - Self { collection } - } - - pub async fn create(&self, stat: HealthStatistic) -> Result> { - self.collection.insert_one(stat.clone(), None).await?; - Ok(stat) - } - - pub async fn list_by_user( - &self, - user_id: &str, - stat_type: Option<&str>, - profile_id: Option<&str>, - limit: i64, - ) -> Result, Box> { - let mut filter = doc! { - "userId": user_id - }; - - if let Some(stat_type) = stat_type { - filter.insert("statType", stat_type); - } - - if let Some(profile_id) = profile_id { - filter.insert("profileId", profile_id); - } - - let find_options = mongodb::options::FindOptions::builder() - .sort(doc! { "recordedAt": -1 }) - .limit(limit) - .build(); - - let cursor = self.collection.find(filter, find_options).await?; - let results: Vec<_> = cursor.try_collect().await?; - Ok(results) - } - - pub async fn get_by_id(&self, id: &ObjectId, user_id: &str) -> Result, Box> { - let filter = doc! { - "_id": id, - "userId": user_id - }; - let result = self.collection.find_one(filter, None).await?; - Ok(result) - } - - pub async fn update( - &self, - id: &ObjectId, - user_id: &str, - update: UpdateHealthStatRequest, - ) -> Result, Box> { - let filter = doc! { - "_id": id, - "userId": user_id - }; - - let mut update_doc = doc! {}; - - if let Some(value) = update.value { - update_doc.insert("value", mongodb::bson::to_bson(&value)?); - } - if let Some(unit) = update.unit { - update_doc.insert("unit", unit); - } - if let Some(recorded_at) = update.recorded_at { - update_doc.insert("recordedAt", recorded_at); - } - if let Some(notes) = update.notes { - update_doc.insert("notes", notes); - } - if let Some(tags) = update.tags { - update_doc.insert("tags", tags); - } - - update_doc.insert("updatedAt", DateTime::now()); - - let update = doc! { - "$set": update_doc - }; - - let result = self.collection.update_one(filter, update, None).await?; - if result.modified_count > 0 { - self.get_by_id(id, user_id).await - } else { - Ok(None) - } - } - - pub async fn delete(&self, id: &ObjectId, user_id: &str) -> Result> { - let filter = doc! { - "_id": id, - "userId": user_id - }; - let result = self.collection.delete_one(filter, None).await?; - Ok(result.deleted_count > 0) - } - - pub async fn get_trends( - &self, - user_id: &str, - profile_id: &str, - stat_type: &str, - days: i64, - ) -> Result, Box> { - // Use chrono duration instead of DateTime arithmetic - let now = chrono::Utc::now(); - let days_ago = now - chrono::Duration::days(days); - let days_ago_bson = DateTime::from_chrono(days_ago); - - let filter = doc! { - "userId": user_id, - "profileId": profile_id, - "statType": stat_type, - "recordedAt": { "$gte": days_ago_bson } - }; - - let find_options = mongodb::options::FindOptions::builder() - .sort(doc! { "recordedAt": 1 }) - .build(); - - let cursor = self.collection.find(filter, find_options).await?; - let results: Vec<_> = cursor.try_collect().await?; - Ok(results) - } -} diff --git a/backend/src/models/mod.rs b/backend/src/models/mod.rs index 94f8ce7..3a255ce 100644 --- a/backend/src/models/mod.rs +++ b/backend/src/models/mod.rs @@ -1,11 +1,11 @@ -pub mod audit_log; +pub mod user; pub mod family; -pub mod health_stats; +pub mod profile; +pub mod health_data; pub mod lab_result; pub mod medication; -pub mod permission; -pub mod profile; -pub mod refresh_token; -pub mod session; +pub mod appointment; pub mod share; -pub mod user; +pub mod permission; +pub mod session; +pub mod audit_log; diff --git a/backend/test-med-v2.sh b/backend/test-med-v2.sh deleted file mode 100755 index 5614cb5..0000000 --- a/backend/test-med-v2.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -BASE_URL="http://localhost:8001" - -echo "=== Phase 2.7 Medication API Tests ===" -echo "" - -# Test 1: Register -echo "Test 1: Register User" -RND=$((10000 + RANDOM % 90000)) -REGISTER=$(curl -s -X POST -H "Content-Type: application/json" \ - -d '{"email":"test'$RND'@example.com","username":"test'$RND'","password":"password123"}' \ - "$BASE_URL/api/auth/register") -echo "$REGISTER" -TOKEN=$(echo "$REGISTER" | grep -o '"token":"[^"]*"' | cut -d'"' -f4 | head -1) -USER_ID=$(echo "$REGISTER" | grep -o '"user_id":"[^"]*"' | cut -d'"' -f4 | head -1) -echo "Token: ${TOKEN:0:50}..." -echo "User ID: $USER_ID" -echo "" - -# Test 2: Create Medication -echo "Test 2: Create Medication" -CREATE=$(curl -s -w "\nStatus: %{http_code}" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"profile_id":"'$USER_ID'","name":"Aspirin","dosage":"81mg","frequency":"daily"}' \ - "$BASE_URL/api/medications") -echo "$CREATE" -MED_ID=$(echo "$CREATE" | grep -o '"id":"[^"]*"' | cut -d'"' -f4 | head -1) -echo "Med ID: $MED_ID" -echo "" - -# Test 3: List Medications -echo "Test 3: List Medications" -curl -s -w "\nStatus: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications" -echo "" - -# Test 4: Get Specific Medication -if [ -n "$MED_ID" ]; then - echo "Test 4: Get Medication $MED_ID" - curl -s -w "\nStatus: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications/$MED_ID" - echo "" -fi - -# Test 5: Update Medication -if [ -n "$MED_ID" ]; then - echo "Test 5: Update Medication" - curl -s -w "\nStatus: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"name":"Aspirin Updated"}' \ - "$BASE_URL/api/medications/$MED_ID" - echo "" -fi - -# Test 6: Log Dose -if [ -n "$MED_ID" ]; then - echo "Test 6: Log Dose" - curl -s -w "\nStatus: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"taken":true,"notes":"Taken with food"}' \ - "$BASE_URL/api/medications/$MED_ID/log" - echo "" -fi - -# Test 7: Get Adherence -if [ -n "$MED_ID" ]; then - echo "Test 7: Get Adherence" - curl -s -w "\nStatus: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications/$MED_ID/adherence" - echo "" -fi - -# Test 8: Unauthorized Access -echo "Test 8: Unauthorized Access (should be 401)" -curl -s -w "\nStatus: %{http_code}\n" \ - "$BASE_URL/api/medications" -echo "" - -# Test 9: Get User Profile -echo "Test 9: Get User Profile" -curl -s -w "\nStatus: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/users/me" -echo "" - -# Test 10: List Shares -echo "Test 10: List Shares" -curl -s -w "\nStatus: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/shares" -echo "" - -echo "=== Tests Complete ===" diff --git a/backend/test-medication-endpoints.sh b/backend/test-medication-endpoints.sh deleted file mode 100644 index e07f5d9..0000000 --- a/backend/test-medication-endpoints.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -# Normogen Medication Management API Test Suite - -API_URL="http://solaria.solivarez.com.ar:8001" - -TEST_USER="med-test-$(date +%s)@example.com" -TEST_USERNAME="medtest$(date +%s)" -TEST_PASSWORD="SecurePass123!" - -echo "==========================================" -echo "Medication Management API Test Suite" -echo "==========================================" -echo "" - -# Test 1: Health Check -echo "Test 1: Health Check" -HEALTH=$(curl -s "$API_URL/health") -if echo "$HEALTH" | grep -q "ok"; then - echo "โœ“ Health check passed" -else - echo "โœ— Health check failed" - exit 1 -fi -echo "" - -# Test 2: Register User -echo "Test 2: Register New User" -REGISTER=$(curl -s -X POST "$API_URL/api/auth/register" -H "Content-Type: application/json" -d '{"email":"'$TEST_USER'","username":"'$TEST_USERNAME'","password":"'$TEST_PASSWORD'","first_name":"Test","last_name":"User"}') -if echo "$REGISTER" | grep -q "access_token"; then - echo "โœ“ User registration successful" - ACCESS_TOKEN=$(echo "$REGISTER" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) -else - echo "โœ— User registration failed" - exit 1 -fi -echo "" - -# Test 3: Login -echo "Test 3: Login" -LOGIN=$(curl -s -X POST "$API_URL/api/auth/login" -H "Content-Type: application/json" -d '{"email":"'$TEST_USER'","password":"'$TEST_PASSWORD'"}') -if echo "$LOGIN" | grep -q "access_token"; then - echo "โœ“ Login successful" - ACCESS_TOKEN=$(echo "$LOGIN" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) -else - echo "โœ— Login failed" - exit 1 -fi -echo "" - -# Test 4: Create Medication -echo "Test 4: Create Medication" -CREATE=$(curl -s -X POST "$API_URL/api/medications" -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" -d '{"medication_name":"Lisinopril","dosage":"10mg","frequency":"once_daily","instructions":"Take with breakfast","start_date":"2026-03-05"}') -if echo "$CREATE" | grep -q "medication_name"; then - echo "โœ“ Medication created successfully" - MEDICATION_ID=$(echo "$CREATE" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f3) - echo "Medication ID: $MEDICATION_ID" -else - echo "โœ— Medication creation failed" - echo "Response: $CREATE" - exit 1 -fi -echo "" - -# Test 5: List All Medications -echo "Test 5: List All Medications" -LIST=$(curl -s -X GET "$API_URL/api/medications" -H "Authorization: Bearer $ACCESS_TOKEN") -if echo "$LIST" | grep -q "Lisinopril"; then - echo "โœ“ List medications successful" -else - echo "โœ— List medications failed" - echo "Response: $LIST" - exit 1 -fi -echo "" - -# Test 6: Get Specific Medication -echo "Test 6: Get Medication Details" -if [ ! -z "$MEDICATION_ID" ]; then - GET=$(curl -s -X GET "$API_URL/api/medications/$MEDICATION_ID" -H "Authorization: Bearer $ACCESS_TOKEN") - if echo "$GET" | grep -q "Lisinopril"; then - echo "โœ“ Get medication successful" - else - echo "โœ— Get medication failed" - fi -fi -echo "" - -# Test 7: Update Medication -echo "Test 7: Update Medication" -if [ ! -z "$MEDICATION_ID" ]; then - UPDATE=$(curl -s -X PUT "$API_URL/api/medications/$MEDICATION_ID" -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" -d '{"medication_name":"Lisinopril","dosage":"20mg","frequency":"once_daily","instructions":"Take with breakfast","start_date":"2026-03-05"}') - if echo "$UPDATE" | grep -q "20mg"; then - echo "โœ“ Update medication successful" - else - echo "โœ— Update medication failed" - fi -fi -echo "" - -# Test 8: Log Dose - Taken -echo "Test 8: Log Dose (Taken)" -if [ ! -z "$MEDICATION_ID" ]; then - LOG1=$(curl -s -X POST "$API_URL/api/medications/$MEDICATION_ID/log" -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" -d '{"status":"taken","notes":"Taken with breakfast"}') - if echo "$LOG1" | grep -q "logged_at"; then - echo "โœ“ Dose logged successfully (taken)" - else - echo "โœ— Log dose failed" - fi -fi -echo "" - -# Test 9: Calculate Adherence -echo "Test 9: Calculate Adherence" -if [ ! -z "$MEDICATION_ID" ]; then - ADHERENCE=$(curl -s -X GET "$API_URL/api/medications/$MEDICATION_ID/adherence" -H "Authorization: Bearer $ACCESS_TOKEN") - echo "โœ“ Adherence calculated" - echo "Response: $ADHERENCE" -fi -echo "" - -# Test 10: Unauthorized Access Test -echo "Test 10: Unauthorized Access (should fail)" -UNAUTH=$(curl -s -X GET "$API_URL/api/medications") -if echo "$UNAUTH" | grep -q "401\|Unauthorized"; then - echo "โœ“ Unauthorized access properly blocked" -else - echo "โœ— Security issue - unauthorized access not blocked" -fi -echo "" - -# Test 11: Delete Medication -echo "Test 11: Delete Medication" -if [ ! -z "$MEDICATION_ID" ]; then - DELETE=$(curl -s -X DELETE "$API_URL/api/medications/$MEDICATION_ID" -H "Authorization: Bearer $ACCESS_TOKEN") - echo "โœ“ Delete medication successful" -fi -echo "" - -echo "==========================================" -echo "Test Suite Complete" -echo "==========================================" diff --git a/backend/test-solaria-v2.sh b/backend/test-solaria-v2.sh deleted file mode 100644 index dbafbfe..0000000 --- a/backend/test-solaria-v2.sh +++ /dev/null @@ -1,241 +0,0 @@ -#!/bin/bash - -echo "==========================================" -echo "Phase 2.7 MVP - Comprehensive API Test" -echo "Running on Solaria server" -echo "==========================================" -echo "" - -BASE_URL="http://localhost:8001" -MED_ID="" -RANDOM_NUM=0 - -# Test 1: Health Check -echo "๐Ÿ” Test 1: Health Check" -echo "Endpoint: GET /health" -RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" "$BASE_URL/health") -echo "$RESPONSE" -if echo "$RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 2: Register New User -echo "๐Ÿ” Test 2: Register New User" -echo "Endpoint: POST /api/auth/register" -RANDOM_NUM=$((10000 + RANDOM % 90000)) -REGISTER_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -d '{ - "email": "med-test-'$RANDOM_NUM'@example.com", - "username": "medtest'$RANDOM_NUM'", - "password": "password123", - "recovery_phrase": "recovery phrase" - }' \ - "$BASE_URL/api/auth/register") -echo "$REGISTER_RESPONSE" -TOKEN=$(echo "$REGISTER_RESPONSE" | grep -o '"token":"[^"]*"' | cut -d'"' -f4) -USER_ID=$(echo "$REGISTER_RESPONSE" | grep -o '"user_id":"[^"]*"' | cut -d'"' -f4) -if echo "$REGISTER_RESPONSE" | grep -q "HTTP Status: 201"; then - echo "โœ… PASS" - echo "User ID: $USER_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 3: Login with same credentials -echo "๐Ÿ” Test 3: Login" -echo "Endpoint: POST /api/auth/login" -LOGIN_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -d '{ - "email": "med-test-'$RANDOM_NUM'@example.com", - "password": "password123" - }' \ - "$BASE_URL/api/auth/login") -echo "$LOGIN_RESPONSE" -TOKEN=$(echo "$LOGIN_RESPONSE" | grep -o '"token":"[^"]*"' | cut -d'"' -f4) -if [ -n "$TOKEN" ]; then - echo "โœ… PASS" - echo "Token obtained: ${TOKEN:0:50}..." -else - echo "โŒ FAIL" -fi -echo "" - -# Test 4: Create Medication -echo "๐Ÿ” Test 4: Create Medication" -echo "Endpoint: POST /api/medications" -CREATE_MED_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{ - "profile_id": "'$USER_ID'", - "name": "Aspirin", - "dosage": "81mg", - "frequency": "Once daily", - "instructions": "Take with food", - "start_date": "2024-01-01", - "reminders": [{"time": "08:00", "days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]}] - }' \ - "$BASE_URL/api/medications") -echo "$CREATE_MED_RESPONSE" -MED_ID=$(echo "$CREATE_MED_RESPONSE" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4) -if echo "$CREATE_MED_RESPONSE" | grep -q "HTTP Status: 201\|HTTP Status: 200"; then - echo "โœ… PASS" - echo "Medication ID: $MED_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 5: List Medications -echo "๐Ÿ” Test 5: List Medications" -echo "Endpoint: GET /api/medications" -LIST_MEDS_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications") -echo "$LIST_MEDS_RESPONSE" -if echo "$LIST_MEDS_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 6: Get Specific Medication -if [ -n "$MED_ID" ]; then - echo "๐Ÿ” Test 6: Get Specific Medication" - echo "Endpoint: GET /api/medications/$MED_ID" - GET_MED_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications/$MED_ID") - echo "$GET_MED_RESPONSE" - if echo "$GET_MED_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" - else - echo "โŒ FAIL" - fi - echo "" -fi - -# Test 7: Update Medication -if [ -n "$MED_ID" ]; then - echo "๐Ÿ” Test 7: Update Medication" - echo "Endpoint: POST /api/medications/$MED_ID" - UPDATE_MED_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{ - "name": "Aspirin Updated", - "dosage": "100mg" - }' \ - "$BASE_URL/api/medications/$MED_ID") - echo "$UPDATE_MED_RESPONSE" - if echo "$UPDATE_MED_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" - else - echo "โŒ FAIL" - fi - echo "" -fi - -# Test 8: Log Dose -if [ -n "$MED_ID" ]; then - echo "๐Ÿ” Test 8: Log Dose" - echo "Endpoint: POST /api/medications/$MED_ID/log" - LOG_DOSE_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{ - "taken": true, - "scheduled_time": "2024-01-01T08:00:00Z", - "notes": "Taken with breakfast" - }' \ - "$BASE_URL/api/medications/$MED_ID/log") - echo "$LOG_DOSE_RESPONSE" - if echo "$LOG_DOSE_RESPONSE" | grep -q "HTTP Status: 201\|HTTP Status: 200"; then - echo "โœ… PASS" - else - echo "โŒ FAIL" - fi - echo "" -fi - -# Test 9: Get Adherence -if [ -n "$MED_ID" ]; then - echo "๐Ÿ” Test 9: Get Adherence" - echo "Endpoint: GET /api/medications/$MED_ID/adherence" - ADHERENCE_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/medications/$MED_ID/adherence") - echo "$ADHERENCE_RESPONSE" - if echo "$ADHERENCE_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" - else - echo "โŒ FAIL" - fi - echo "" -fi - -# Test 10: Unauthorized Access (No Token) -echo "๐Ÿ” Test 10: Unauthorized Access (No Token)" -echo "Endpoint: GET /api/medications" -UNAUTH_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - "$BASE_URL/api/medications") -echo "$UNAUTH_RESPONSE" -if echo "$UNAUTH_RESPONSE" | grep -q "HTTP Status: 401"; then - echo "โœ… PASS - Correctly blocked unauthorized access" -else - echo "โŒ FAIL - Should return 401" -fi -echo "" - -# Test 11: Get User Profile -echo "๐Ÿ” Test 11: Get User Profile" -echo "Endpoint: GET /api/users/me" -PROFILE_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/users/me") -echo "$PROFILE_RESPONSE" -if echo "$PROFILE_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 12: List Shares -echo "๐Ÿ” Test 12: List Shares" -echo "Endpoint: GET /api/shares" -SHARES_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/shares") -echo "$SHARES_RESPONSE" -if echo "$SHARES_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 13: Get Sessions -echo "๐Ÿ” Test 13: Get Sessions" -echo "Endpoint: GET /api/sessions" -SESSIONS_RESPONSE=$(curl -s -w "\nHTTP Status: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - "$BASE_URL/api/sessions") -echo "$SESSIONS_RESPONSE" -if echo "$SESSIONS_RESPONSE" | grep -q "HTTP Status: 200"; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -echo "==========================================" -echo "All Tests Complete!" -echo "==========================================" diff --git a/quick-test.sh b/quick-test.sh deleted file mode 100644 index c517fc6..0000000 --- a/quick-test.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -curl http://solaria.solivarez.com.ar:8001/health diff --git a/solaria-test.sh b/solaria-test.sh deleted file mode 100644 index 2f89871..0000000 --- a/solaria-test.sh +++ /dev/null @@ -1,264 +0,0 @@ -#!/bin/bash - -API_URL="http://localhost:8001" -USER_EMAIL="med-test-${RANDOM}@example.com" -USER_NAME="medtest${RANDOM}" - -echo "==========================================" -echo "Phase 2.7 MVP - Comprehensive API Test" -echo "Running on Solaria server" -echo "==========================================" -echo "" - -# Test 1: Health Check -echo "๐Ÿ” Test 1: Health Check" -echo "Endpoint: GET /health" -HEALTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" ${API_URL}/health) -HTTP_CODE=$(echo "$HEALTH" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$HEALTH" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 2: Register User -echo "๐Ÿ” Test 2: Register New User" -echo "Endpoint: POST /api/auth/register" -REGISTER=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/register \ - -H "Content-Type: application/json" \ - -d '{"email":"'${USER_EMAIL}'","username":"'${USER_NAME}'","password":"SecurePass123!","first_name":"Test","last_name":"User"}') -HTTP_CODE=$(echo "$REGISTER" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$REGISTER" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" - USER_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | cut -d'"' -f4) - echo "User ID: $USER_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 3: Login -echo "๐Ÿ” Test 3: Login" -echo "Endpoint: POST /api/auth/login" -LOGIN=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"'${USER_EMAIL}'","password":"SecurePass123!"}') -HTTP_CODE=$(echo "$LOGIN" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LOGIN" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - TOKEN=$(echo "$BODY" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) - echo "Token obtained: ${TOKEN:0:20}..." -else - echo "โŒ FAIL" - exit 1 -fi -echo "" - -# Test 4: Create Medication -echo "๐Ÿ” Test 4: Create Medication" -echo "Endpoint: POST /api/medications" -CREATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"profile_id":null,"name":"Lisinopril","dosage":"10mg","frequency":"once_daily","instructions":"Take with breakfast","start_date":"2026-03-01"}') -HTTP_CODE=$(echo "$CREATE_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$CREATE_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" - MED_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4) - echo "Medication ID: $MED_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 5: List Medications -echo "๐Ÿ” Test 5: List Medications" -echo "Endpoint: GET /api/medications" -LIST_MEDS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$LIST_MEDS" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LIST_MEDS" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - MED_COUNT=$(echo "$BODY" | grep -o '"medication_id"' | wc -l) - echo "Medications found: $MED_COUNT" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 6: Get Specific Medication -echo "๐Ÿ” Test 6: Get Specific Medication" -echo "Endpoint: GET /api/medications/$MED_ID" -GET_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$GET_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$GET_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 7: Update Medication -echo "๐Ÿ” Test 7: Update Medication" -echo "Endpoint: PUT /api/medications/$MED_ID" -UPDATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X PUT ${API_URL}/api/medications/$MED_ID \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"dosage":"20mg","instructions":"Take with breakfast and dinner"}') -HTTP_CODE=$(echo "$UPDATE_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$UPDATE_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - UPDATED_DOSAGE=$(echo "$BODY" | grep -o '"dosage":"[^"]*' | cut -d'"' -f4) - echo "Updated dosage: $UPDATED_DOSAGE" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 8: Log Dose -echo "๐Ÿ” Test 8: Log Dose" -echo "Endpoint: POST /api/medications/$MED_ID/log" -LOG_DOSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/log \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"taken":true,"scheduled_time":"2026-03-07T08:00:00Z","notes":"Taken with breakfast"}') -HTTP_CODE=$(echo "$LOG_DOSE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LOG_DOSE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 9: Get Adherence -echo "๐Ÿ” Test 9: Get Adherence" -echo "Endpoint: GET /api/medications/$MED_ID/adherence" -ADHERENCE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID/adherence \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$ADHERENCE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$ADHERENCE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - ADH_PCT=$(echo "$BODY" | grep -o '"adherence_percentage":[0-9.]*' | cut -d: -f2) - echo "Adherence: $ADH_PCT%" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 10: Unauthorized Access -echo "๐Ÿ” Test 10: Unauthorized Access (No Token)" -echo "Endpoint: GET /api/medications" -UNAUTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications) -HTTP_CODE=$(echo "$UNAUTH" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "401" ]; then - echo "โœ… PASS - Correctly blocked unauthorized access" -else - echo "โŒ FAIL - Should return 401" -fi -echo "" - -# Test 11: Get Profile -echo "๐Ÿ” Test 11: Get User Profile" -echo "Endpoint: GET /api/users/me" -PROFILE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/users/me \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$PROFILE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$PROFILE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 12: Delete Medication -echo "๐Ÿ” Test 12: Delete Medication" -echo "Endpoint: POST /api/medications/$MED_ID/delete" -DELETE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/delete \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$DELETE_MED" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS - Medication deleted" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 13: List Shares -echo "๐Ÿ” Test 13: List Shares" -echo "Endpoint: GET /api/shares" -SHARES=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/shares \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$SHARES" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 14: Get Sessions -echo "๐Ÿ” Test 14: Get Sessions" -echo "Endpoint: GET /api/sessions" -SESSIONS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/sessions \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$SESSIONS" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 15: Logout -echo "๐Ÿ” Test 15: Logout" -echo "Endpoint: POST /api/auth/logout" -LOGOUT=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/logout \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$LOGOUT" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -echo "==========================================" -echo "All Tests Complete!" -echo "==========================================" diff --git a/test-medication-api.sh b/test-medication-api.sh deleted file mode 100755 index 937945b..0000000 --- a/test-medication-api.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -API_URL="http://solaria.solivarez.com.ar:8001" - -echo "Testing Medication Management API" -echo "==================================" - -echo "" -echo "1. Health Check" -curl -s "$API_URL/health" -echo "" - -echo "" -echo "2. Register User" -REGISTER=$(curl -s -X POST "$API_URL/api/auth/register" \ - -H "Content-Type: application/json" \ - -d '{"email":"med-test@example.com","username":"medtest","password":"SecurePass123!","first_name":"Test","last_name":"User"}') -echo "$REGISTER" - -echo "" -echo "3. Login" -LOGIN=$(curl -s -X POST "$API_URL/api/auth/login" \ - -H "Content-Type: application/json" \ - -d '{"email":"med-test@example.com","password":"SecurePass123!"}') -echo "$LOGIN" - -TOKEN=$(echo "$LOGIN" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) -echo "" -echo "Token obtained" - -echo "" -echo "4. Create Medication" -CREATE=$(curl -s -X POST "$API_URL/api/medications" \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"profile_id":null,"medication_name":"Lisinopril","dosage":"10mg","frequency":"once_daily","instructions":"Take with breakfast"}') -echo "$CREATE" - -echo "" -echo "5. List Medications" -curl -s -X GET "$API_URL/api/medications" \ - -H "Authorization: Bearer $TOKEN" -echo "" - -echo "" -echo "Tests complete!" diff --git a/test-meds.sh b/test-meds.sh deleted file mode 100755 index e793e2a..0000000 --- a/test-meds.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -echo "Testing Medication API" -curl -s http://solaria.solivarez.com.ar:8001/health -echo "" -echo "Registering user..." -curl -s -X POST http://solaria.solivarez.com.ar:8001/api/auth/register -H "Content-Type: application/json" -d '{"email":"medtest@example.com","username":"medtest","password":"Password123!","first_name":"Test","last_name":"User"}' diff --git a/test-mvp-phase-2.7.sh b/test-mvp-phase-2.7.sh deleted file mode 100755 index 860d2c3..0000000 --- a/test-mvp-phase-2.7.sh +++ /dev/null @@ -1,219 +0,0 @@ -#!/bin/bash - -API_URL="http://solaria.solivarez.com.ar:8001" -USER_EMAIL="med-test-${RANDOM}@example.com" -USER_NAME="medtest${RANDOM}" - -echo "==========================================" -echo "Phase 2.7 MVP - Comprehensive API Test" -echo "==========================================" -echo "" - -# Test 1: Health Check -echo "๐Ÿ” Test 1: Health Check" -echo "Endpoint: GET /health" -HEALTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" ${API_URL}/health) -HTTP_CODE=$(echo "$HEALTH" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$HEALTH" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 2: Register User -echo "๐Ÿ” Test 2: Register New User" -echo "Endpoint: POST /api/auth/register" -REGISTER=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/register \ - -H "Content-Type: application/json" \ - -d '{"email":"'${USER_EMAIL}'","username":"'${USER_NAME}'","password":"SecurePass123!","first_name":"Test","last_name":"User"}') -HTTP_CODE=$(echo "$REGISTER" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$REGISTER" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" - # Extract user ID - USER_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | cut -d'"' -f4) - echo "User ID: $USER_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 3: Login -echo "๐Ÿ” Test 3: Login" -echo "Endpoint: POST /api/auth/login" -LOGIN=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email":"'${USER_EMAIL}'","password":"SecurePass123!"}') -HTTP_CODE=$(echo "$LOGIN" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LOGIN" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - # Extract token - TOKEN=$(echo "$BODY" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) - echo "Token obtained: ${TOKEN:0:20}..." -else - echo "โŒ FAIL" - exit 1 -fi -echo "" - -# Test 4: Create Medication -echo "๐Ÿ” Test 4: Create Medication" -echo "Endpoint: POST /api/medications" -CREATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"profile_id":null,"name":"Lisinopril","dosage":"10mg","frequency":"once_daily","instructions":"Take with breakfast","start_date":"2026-03-01"}') -HTTP_CODE=$(echo "$CREATE_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$CREATE_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" - MED_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4) - echo "Medication ID: $MED_ID" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 5: List Medications -echo "๐Ÿ” Test 5: List Medications" -echo "Endpoint: GET /api/medications" -LIST_MEDS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$LIST_MEDS" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LIST_MEDS" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 6: Get Specific Medication -echo "๐Ÿ” Test 6: Get Specific Medication" -echo "Endpoint: GET /api/medications/$MED_ID" -GET_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$GET_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$GET_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 7: Update Medication -echo "๐Ÿ” Test 7: Update Medication" -echo "Endpoint: PUT /api/medications/$MED_ID" -UPDATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X PUT ${API_URL}/api/medications/$MED_ID \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"dosage":"20mg","instructions":"Take with breakfast and dinner"}') -HTTP_CODE=$(echo "$UPDATE_MED" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$UPDATE_MED" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 8: Log Dose -echo "๐Ÿ” Test 8: Log Dose" -echo "Endpoint: POST /api/medications/$MED_ID/log" -LOG_DOSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/log \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $TOKEN" \ - -d '{"taken":true,"scheduled_time":"2026-03-07T08:00:00Z","notes":"Taken with breakfast"}') -HTTP_CODE=$(echo "$LOG_DOSE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$LOG_DOSE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "201" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 9: Get Adherence -echo "๐Ÿ” Test 9: Get Adherence" -echo "Endpoint: GET /api/medications/$MED_ID/adherence" -ADHERENCE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID/adherence \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$ADHERENCE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$ADHERENCE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" - ADH_PCT=$(echo "$BODY" | grep -o '"adherence_percentage":[0-9.]*' | cut -d: -f2) - echo "Adherence: $ADH_PCT%" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 10: Unauthorized Access -echo "๐Ÿ” Test 10: Unauthorized Access (No Token)" -echo "Endpoint: GET /api/medications" -UNAUTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications) -HTTP_CODE=$(echo "$UNAUTH" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "401" ]; then - echo "โœ… PASS - Correctly blocked unauthorized access" -else - echo "โŒ FAIL - Should return 401" -fi -echo "" - -# Test 11: Get Profile -echo "๐Ÿ” Test 11: Get User Profile" -echo "Endpoint: GET /api/users/me" -PROFILE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/users/me \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$PROFILE" | grep "HTTP_CODE" | cut -d: -f2) -BODY=$(echo "$PROFILE" | sed '/HTTP_CODE/d') -echo "Response: $BODY" -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "200" ]; then - echo "โœ… PASS" -else - echo "โŒ FAIL" -fi -echo "" - -# Test 12: Delete Medication -echo "๐Ÿ” Test 12: Delete Medication" -echo "Endpoint: POST /api/medications/$MED_ID/delete" -DELETE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/delete \ - -H "Authorization: Bearer $TOKEN") -HTTP_CODE=$(echo "$DELETE_MED" | grep "HTTP_CODE" | cut -d: -f2) -echo "HTTP Status: $HTTP_CODE" -if [ "$HTTP_CODE" = "204" ]; then - echo "โœ… PASS - No content (successful deletion)" -else - echo "โŒ FAIL" -fi -echo "" - -echo "==========================================" -echo "Test Complete!" -echo "=========================================="