Skip to content

Add OAuth providers migration#191

Open
premtsd-code wants to merge 26 commits into
mainfrom
add-oauth-providers-migration
Open

Add OAuth providers migration#191
premtsd-code wants to merge 26 commits into
mainfrom
add-oauth-providers-migration

Conversation

@premtsd-code
Copy link
Copy Markdown
Contributor

Summary

  • Adds TYPE_OAUTH_PROVIDERS to GROUP_AUTH_RESOURCES for migrating the project's OAuth2 provider configuration map.
  • Source (Sources/Appwrite) reads $project->oAuthProviders and emits one OAuthProviders singleton carrying key/enabled/appId for each provider.
  • Destination (Destinations/Appwrite) merges the entries into the project doc's oAuthProviders map as flat {key}Enabled / {key}Appid keys via dbForPlatform (mirrors the destination path used by auth-methods / policies).
  • {key}Secret is intentionally not migrated — the source API never exposes secrets and the destination user must re-enter them post-migration. Same caveat as the SMTP password handling.
  • Grouped under GROUP_AUTH (not GROUP_INTEGRATIONS) — OAuth providers are auth methods that happen to use external identity providers; same group as TYPE_AUTH_METHODS and TYPE_POLICIES.

Test plan

  • CI lints + tests green
  • E2E testAppwriteMigrationOAuthProviders (in appwrite/appwrite) passes

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Greptile Summary

Adds OAuth2 provider configuration migration between Appwrite projects. The source reads the provider list via listOAuth2Providers, maps each entry through an allow-list that routes clientId-family fields to {key}Appid and non-secret config (endpoints, tenant, etc.) to the {key}Secret JSON blob, then the destination merges those values into the project's oAuthProviders map via a direct platform DB write — mirroring the pattern already used for auth-methods and policies. Client secrets are intentionally not migrated.

  • OAuth2Provider.php introduces the new resource class with a provider allow-list; getDestinationAppId / getDestinationSecretFields encapsulate routing so the destination never needs to know per-provider field names.
  • Destinations/Appwrite.php gains createOAuth2Provider and the reusable mergeJsonSecret helper; the guard/enabled issues from earlier review iterations have been removed in favour of unconditional state copy.
  • Tests cover mergeJsonSecret edge cases and provider field routing for Google and Apple.

Confidence Score: 5/5

Safe to merge; all correctness and security concerns from prior review rounds appear resolved, and the new code faithfully copies provider state without exposing secrets.

The allow-list design prevents secret leakage, the enabled/secret guard problems flagged in earlier rounds are gone, and the mergeJsonSecret merge-and-preserve logic is well-tested. The remaining observations are efficiency notes (N DB round-trips per provider, duplicate API call) that do not affect migration correctness.

The per-provider read-write-purge loop in Destinations/Appwrite.php::createOAuth2Provider and the duplicate listOAuth2Providers call in Sources/Appwrite.php::getOAuth2ProviderResources are worth revisiting before this scales to projects with many configured providers.

Important Files Changed

Filename Overview
src/Migration/Resources/Auth/OAuth2/OAuth2Provider.php New resource class. Allow-list design correctly prevents secret leakage; getDestinationAppId/getDestinationSecretFields cleanly separate appId and secret routing; fromArray and isConfigured handle all edge cases correctly.
src/Migration/Destinations/Appwrite.php New createOAuth2Provider correctly merges into the oAuthProviders map and uses the fixed-up mergeJsonSecret; however it issues N separate DB read/write/purge cycles (one per provider) where a single batch write would suffice.
src/Migration/Sources/Appwrite.php Export logic is correct and well-guarded; getOAuth2ProviderResources is called twice (report phase + export phase), making duplicate listOAuth2Providers() API calls.
src/Migration/Resource.php Adds TYPE_OAUTH2_PROVIDER constant in the correct position; registered in ALL_PUBLIC_RESOURCES.
src/Migration/Transfer.php Adds TYPE_OAUTH2_PROVIDER to GROUP_AUTH_RESOURCES and ALL_PUBLIC_RESOURCES; no logic changes.

Reviews (23): Last reviewed commit: "Fix OAuth provider secret field mappings" | Re-trigger Greptile

Comment thread src/Migration/Sources/Appwrite.php
Comment thread src/Migration/Sources/Appwrite.php Outdated
Comment thread src/Migration/Destinations/Appwrite.php Outdated
- Destination: dispatch via explicit case Resource::TYPE_OAUTH2_PROVIDER instead of default + instanceof
- Source: count in report() directly like sibling resources (drop try/catch), and move the in_array guard inside the export try
- Harden mergeAppleSecret/mergeJsonSecret against non-array decoded JSON
- Fix stale OAuth2Provider docblock (single shared TYPE, not per-subclass)
- mergeAppleSecret now delegates to mergeJsonSecret (one merge implementation)
- exportOAuth2Providers surfaces providers with no Resource class as non-fatal
  errors instead of dropping them silently
- report() counts only migratable providers; fix the misleading enabled comment
- use elseif for the mutually-exclusive provider-shape branches
- add AppwriteOAuth2SecretTest (secret-merge) and OAuth2ProviderTransferTest
  (transfer round-trip via MockSource/MockDestination)
…rage

Other migration resources (auth methods, policies, …) ship no per-resource
tests in this library; keep OAuth2 consistent with that baseline.
Comment thread src/Migration/Sources/Appwrite.php Outdated
Base automatically changed from add-email-templates-migration to main June 3, 2026 06:15
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we generalize and have 1 class for all? Much easier to maintain

Replace the per-provider class hierarchy (OAuth2Provider base +
StandardProvider/WithEndpointProvider + ~40 one-line subclasses) with a
single OAuth2Provider class driven by a `providerKey => non-secret fields`
map. Addresses review feedback to have one class for all providers.

- Source dispatch: drop the 42-entry class registry + oauth2ClassFor();
  build providers via OAuth2Provider::fromArray($key, $payload).
- Destination dispatch: replace the instanceof chain with a key check
  (Apple) + data-driven settings routing for endpoint/tenant/prompt.
- The field map doubles as a secret allow-list: only declared non-secret
  fields are copied off the listOAuth2Providers payload, so a future
  upstream secret field cannot leak into the migration.

Net 44 fewer files. Pint, PHPStan level 3, and the Unit suite all pass.
Comment thread src/Migration/Destinations/Appwrite.php Outdated
- Remove unused getSetting(); getDestinationAppId/SecretFields cover all callers.
- getDestinationAppId() now returns ?string (null when unset), so the
  destination drops its duplicate isEmptyOAuth2Setting() helper and isConfigured()
  reads as `enabled || appId !== null`.
- Document the PROVIDERS target/key routing so adding a provider is self-explanatory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants