diff --git a/CHANGELOG.md b/CHANGELOG.md index b577016..393be0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to Medical Tracker are documented here. - Added openFDA brand-name and substance-name buckets to the medicine source updater. - Added official medicine-use fields and source links populated from openFDA drug label `indications_and_usage` or `purpose` text. - Added computed `used_for` values to medicine API payloads so clients can display official label use text when available. +- Added `config/public-access.json` toggles for disabling Admin and Tracker on public deployments. ### Changed @@ -24,6 +25,7 @@ All notable changes to Medical Tracker are documented here. - Updated relationship generation so official medicine-use label text participates in condition and symptom linking. - Updated openFDA refreshes to fetch label documents first, then fall back to generic, brand, and substance buckets for broader coverage. - Renamed user-facing branding from "Neon Medical Tracker" to "Medical Tracker". +- Updated public navigation, route guards, legacy signup redirect, and API write actions to honor the Admin/Tracker access toggles. - Batched imported medicine upserts inside a SQLite transaction for faster source refreshes. - Increased SQLite busy timeout for safer first-run migrations and source refreshes. - Updated `README.md` with current counts, relationship data, and source-refresh behavior. @@ -85,7 +87,7 @@ All notable changes to Medical Tracker are documented here. - Removed the `public_signup` API action. - Removed signup links from the public header, footer, homepage, and condition pages. - Removed unused signup/showcase CSS from the public stylesheet. -- Replaced `/signup.php` with a simple redirect to `/tracker.php` for legacy links. +- Replaced `/signup.php` with a simple redirect for legacy links. ### Fixed @@ -97,7 +99,7 @@ All notable changes to Medical Tracker are documented here. ### Verified - Verified dynamic medicine, symptom, condition, and terminology routes return `200` for representative records. -- Verified legacy `/signup.php` returns `302` to `/tracker.php`. +- Verified legacy `/signup.php` returns a `302` redirect. - Verified `api.php?action=public_signup` returns `404`. - Verified then-current SQLite snapshot counts: 6,002 medicines, 242 symptoms, 203 conditions, 23 terms, and 9 research-link categories. - Verified browser layout checks for medicine, symptom, and terminology pages at desktop and mobile widths with no horizontal overflow. diff --git a/README.md b/README.md index 752e9c7..660f427 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ http://127.0.0.1:8080 ## Public Routes -- `/` - medical reference hub with search, database totals, and links to tracker/admin tools. +- `/` - medical reference hub with search, database totals, and optional tracker/admin links when enabled. - `/nutrition.php` - searchable medicine catalog. - `/medicine.php?id=46` - dynamic medicine detail page backed by SQLite. - `/symptoms.php` - searchable symptom reference database. @@ -28,9 +28,28 @@ http://127.0.0.1:8080 - `/medical.php` - combined search for symptoms, terminology, conditions, medicines, and study links. - `/term.php?id=1` - dynamic medical terminology detail page backed by SQLite. - `/recovery.php` - NIH/NLM research and study-link categories. -- `/tracker.php` - profile-scoped medical tracker dashboard. -- `/admin.php` - admin user-management dashboard and medicine-source updater. -- `/signup.php` - legacy route that redirects to `/tracker.php`; public signup has been removed. +- `/tracker.php` - profile-scoped medical tracker dashboard when enabled. +- `/admin.php` - admin user-management dashboard and medicine-source updater when enabled. +- `/signup.php` - legacy route that redirects to `/tracker.php` when tracker is enabled, otherwise `/`; public signup has been removed. + +## Public Access Toggle + +Private profile tools are controlled by: + +```text +config/public-access.json +``` + +The default public-safe configuration is: + +```json +{ + "admin_area_enabled": false, + "tracker_area_enabled": false +} +``` + +When an area is disabled, its navigation links are hidden, direct page visits return a disabled public page, and related API write endpoints return `403`. Set either value to `true` to re-enable that area. ## Current Data @@ -96,13 +115,15 @@ public/api.php Useful actions: -- `GET api.php?action=state` - tracker/admin state payload. +- `GET api.php?action=state` - tracker/admin state payload when at least one private area is enabled. - `GET api.php?action=library_search&q=chest&limit=20` - combined reference search. - `POST api.php?action=create_user` - create a user profile from admin/tracker tools. - `POST api.php?action=update_user` - update a user profile. - `POST api.php?action=delete_user` - delete a user profile. - `POST api.php?action=refresh_medication_sources` - refresh the medicine catalog from configured public sources. +Private-area API actions return `403` when the matching Admin or Tracker toggle is disabled. + The old `public_signup` action has been removed. ## Reference Sources @@ -118,6 +139,6 @@ The old `public_signup` action has been removed. ## Notes -- This project intentionally avoids a public signup funnel. Profiles are managed through `/admin.php` and `/tracker.php`. +- This project intentionally avoids a public signup funnel. Profiles are managed through `/admin.php` and `/tracker.php` only when those private areas are enabled. - Dynamic detail pages use shared PHP endpoints and pull records from SQLite; individual medicine, symptom, condition, and term pages do not need to exist as separate files. - Legacy workout, nutrition, and supplement tracker data remains in the schema as wellness context, but the public app focus is now medical tracking and reference lookup. diff --git a/app/bootstrap.php b/app/bootstrap.php index c0d5fca..42a7e21 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -4,9 +4,57 @@ declare(strict_types=1); date_default_timezone_set('America/New_York'); const APP_ROOT = __DIR__ . '/..'; +const CONFIG_DIR = APP_ROOT . '/config'; +const PUBLIC_ACCESS_CONFIG_PATH = CONFIG_DIR . '/public-access.json'; const DATA_DIR = APP_ROOT . '/data'; const DB_PATH = DATA_DIR . '/health_tracker.sqlite'; +function public_access_config(): array +{ + static $config = null; + + if (is_array($config)) { + return $config; + } + + $config = [ + 'admin_area_enabled' => false, + 'tracker_area_enabled' => false, + ]; + + if (!is_file(PUBLIC_ACCESS_CONFIG_PATH)) { + return $config; + } + + $json = json_decode((string) file_get_contents(PUBLIC_ACCESS_CONFIG_PATH), true); + if (!is_array($json)) { + return $config; + } + + foreach ($config as $key => $default) { + if (array_key_exists($key, $json)) { + $config[$key] = filter_var($json[$key], FILTER_VALIDATE_BOOLEAN); + } + } + + return $config; +} + +function app_admin_area_enabled(): bool +{ + return public_access_config()['admin_area_enabled']; +} + +function app_tracker_area_enabled(): bool +{ + return public_access_config()['tracker_area_enabled']; +} + +function app_private_tools_enabled(): bool +{ + return app_admin_area_enabled() || app_tracker_area_enabled(); +} + function app_db(): PDO { static $pdo = null; @@ -2698,7 +2746,7 @@ function state_payload(array $query): array } } $userId = (int) $currentUser['id']; - $currentUserIsAdmin = is_admin($pdo, $userId); + $currentUserIsAdmin = app_admin_area_enabled() && is_admin($pdo, $userId); $exercises = db_all( $pdo, diff --git a/config/public-access.json b/config/public-access.json new file mode 100644 index 0000000..721796c --- /dev/null +++ b/config/public-access.json @@ -0,0 +1,4 @@ +{ + "admin_area_enabled": false, + "tracker_area_enabled": false +} diff --git a/public/admin.php b/public/admin.php index b8b94d9..21b2369 100644 --- a/public/admin.php +++ b/public/admin.php @@ -2,6 +2,26 @@ declare(strict_types=1); require __DIR__ . '/../app/bootstrap.php'; + +if (!app_admin_area_enabled()) { + http_response_code(404); + $pageTitle = 'Admin Unavailable | Medical Tracker'; + $activePage = ''; + require __DIR__ . '/partials/site-header.php'; + ?> +
+
+

Private area disabled

+

Admin is not available.

+

This public site is currently configured for reference browsing only.

+ Return home +
+
+ Acting profile - Open tracker + + Open tracker +
- Open tracker + + Open tracker + Condition search
diff --git a/public/index.php b/public/index.php index ec1ddbb..a381743 100644 --- a/public/index.php +++ b/public/index.php @@ -11,6 +11,8 @@ $totalTerms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_terms'); $totalSymptoms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_symptoms'); $totalConditions = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_conditions'); $totalStudies = (int) db_value($pdo, 'SELECT COUNT(*) FROM research_studies'); +$trackerAreaEnabled = app_tracker_area_enabled(); +$adminAreaEnabled = app_admin_area_enabled(); require __DIR__ . '/partials/site-header.php'; ?> @@ -19,7 +21,7 @@ require __DIR__ . '/partials/site-header.php';

Medical reference

Medicines, symptoms, terminology, conditions, and NIH/NLM study links.

-

Search the reference database or open the tracker/admin tools for profile-managed medical logs.

+

Search the public reference database for medicine, condition, symptom, terminology, and research links.