diff --git a/apps/gateway/src/apps.rs b/apps/gateway/src/apps.rs index 9e68365..2028ce5 100644 --- a/apps/gateway/src/apps.rs +++ b/apps/gateway/src/apps.rs @@ -234,6 +234,16 @@ static APP_PROVIDERS: &[AppProvider] = &[ }], refresh: Some(&GOOGLE_REFRESH), }, + AppProvider { + provider: "google-health", + display_name: "Google Health", + host_rules: &[HostRule { + host: "health.googleapis.com", + path_prefix: None, + strategy: AuthStrategy::Bearer, + }], + refresh: Some(&GOOGLE_REFRESH), + }, AppProvider { provider: "resend", display_name: "Resend", @@ -658,6 +668,10 @@ mod tests { providers_for_host("photoslibrary.googleapis.com"), vec!["google-photos"] ); + assert_eq!( + providers_for_host("health.googleapis.com"), + vec!["google-health"] + ); } #[test] @@ -674,6 +688,7 @@ mod tests { ("google-search-console", "searchconsole.googleapis.com"), ("google-meet", "meet.googleapis.com"), ("google-photos", "photoslibrary.googleapis.com"), + ("google-health", "health.googleapis.com"), ]; for (provider, host) in &hosts { let injections = build_app_injections(provider, host, "ya29.test"); diff --git a/apps/web/public/icons/google-health.svg b/apps/web/public/icons/google-health.svg new file mode 100644 index 0000000..769e1c3 --- /dev/null +++ b/apps/web/public/icons/google-health.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/web/src/lib/apps/google-health.ts b/apps/web/src/lib/apps/google-health.ts new file mode 100644 index 0000000..c88573f --- /dev/null +++ b/apps/web/src/lib/apps/google-health.ts @@ -0,0 +1,86 @@ +import type { AppDefinition } from "./types"; +import { + buildGoogleAuthUrl, + exchangeGoogleCode, + googleConfigFields, + googleEnvDefaults, +} from "./google-oauth"; + +export const googleHealth: AppDefinition = { + id: "google-health", + name: "Google Health", + icon: "/icons/google-health.svg", + description: + "Access activity, sleep, and health metrics from Fitbit and connected devices.", + connectionMethod: { + type: "oauth", + defaultScopes: [ + "openid", + "email", + "profile", + "https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly", + "https://www.googleapis.com/auth/googlehealth.sleep.readonly", + "https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly", + ], + permissions: [ + { + scope: + "https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly", + name: "Activity & fitness", + description: "Steps, exercise, and activity data", + access: "read", + }, + { + scope: "https://www.googleapis.com/auth/googlehealth.sleep.readonly", + name: "Sleep", + description: "Sleep stages, duration, and quality data", + access: "read", + }, + { + scope: + "https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly", + name: "Health metrics", + description: "Body metrics such as weight, body fat, and heart rate", + access: "read", + }, + { + scope: + "https://www.googleapis.com/auth/googlehealth.nutrition.readonly", + name: "Nutrition", + description: "Logged food and nutrition data", + access: "read", + }, + { + scope: "https://www.googleapis.com/auth/googlehealth.location.readonly", + name: "Exercise location", + description: "GPS tracks recorded during exercise", + access: "read", + }, + { + scope: "https://www.googleapis.com/auth/googlehealth.profile.readonly", + name: "Profile", + description: "Health profile details", + access: "read", + }, + { + scope: "https://www.googleapis.com/auth/userinfo.email", + name: "Email address", + description: "View your email address", + access: "read", + }, + { + scope: "https://www.googleapis.com/auth/userinfo.profile", + name: "Profile", + description: "Name and profile picture", + access: "read", + }, + ], + buildAuthUrl: buildGoogleAuthUrl, + exchangeCode: exchangeGoogleCode, + }, + available: true, + configurable: { + fields: googleConfigFields, + envDefaults: googleEnvDefaults, + }, +}; diff --git a/apps/web/src/lib/apps/registry.ts b/apps/web/src/lib/apps/registry.ts index f5aff78..fa112fd 100644 --- a/apps/web/src/lib/apps/registry.ts +++ b/apps/web/src/lib/apps/registry.ts @@ -8,6 +8,7 @@ import { googleClassroom } from "./google-classroom"; import { googleDocs } from "./google-docs"; import { googleDrive } from "./google-drive"; import { googleForms } from "./google-forms"; +import { googleHealth } from "./google-health"; import { googleMeet } from "./google-meet"; import { googlePhotos } from "./google-photos"; import { googleSearchConsole } from "./google-search-console"; @@ -26,6 +27,7 @@ export const apps: AppDefinition[] = [ googleDocs, googleDrive, googleForms, + googleHealth, googleMeet, googlePhotos, googleSearchConsole,