Skip to content

Add API key and platform migration support#183

Open
premtsd-code wants to merge 11 commits into
mainfrom
add-api-key-migration
Open

Add API key and platform migration support#183
premtsd-code wants to merge 11 commits into
mainfrom
add-api-key-migration

Conversation

@premtsd-code
Copy link
Copy Markdown
Contributor

Summary

  • Adds API key migration support for the Appwrite source/destination (new ApiKey resource, source export via console headers, destination import).
  • Adds platform migration support (new Platform resource).
  • Pulls in feat-platform-db-access (PR Add platform migration support #154), which switches platform listing/export from console-key HTTP calls to the Project SDK service with buildQueries.

Notes

  • Platforms no longer require console headers — they go through projectService->listPlatforms / exportPlatforms($batchSize).
  • API keys still require console headers and continue to use the exportWithConsoleHeaders wrapper.
  • Stacks on top of the platform-db-access work; if PR Add platform migration support #154 lands first, this diff will shrink accordingly.

Test plan

  • composer install && composer test (vendor not present in worktree — please run locally)
  • composer lint && composer format
  • E2E: migrate a project with API keys + platforms from one Appwrite instance to another, verify both arrive
  • Verify report totals for apiKey and platform resource types

…d-api-key-migration

# Conflicts:
#	src/Migration/Destinations/Appwrite.php
#	src/Migration/Sources/Appwrite.php
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 14, 2026

Greptile Summary

This PR introduces two new resource types — ApiKey and Platform — for Appwrite-to-Appwrite migrations. API keys are exported via the Project SDK service with cursor-based pagination and imported by writing directly into the platform database with a freshly generated secret; platforms follow the same SDK-driven path introduced in PR #154.

  • ApiKey resource (src/Migration/Resources/Integrations/ApiKey.php): New class modelling API key fields; fromArray correctly null-coalesces optional SDK fields, but the export loop in Sources/Appwrite.php passes $key->expire and $key->accessedAt directly to the constructor without null-coalescing, producing a TypeError for every key with no expiry date or no usage history.
  • createApiKey destination handler (src/Migration/Destinations/Appwrite.php): Writes keys to the platform DB with a regenerated secret and purgeCachedDocument post-write, but uses Role::any() permissions on each document rather than scoping access to the project owner or admin roles.
  • Pagination and reporting: exportApiKeys correctly uses a cursorAfter loop; reportIntegrations calls $this->project->listKeys() via the SDK service, eliminating the earlier console-header dependency.

Confidence Score: 3/5

Not safe to merge until the null-coalescing gap in exportApiKeys and the overly permissive document permissions in createApiKey are resolved.

Two defects on the hot path make this risky: every API key with no expiry date or no usage history will throw a TypeError during export because $key->expire and $key->accessedAt are passed directly to non-nullable constructor parameters. On the import side, all migrated key documents are created with Role::any() permissions, granting unauthenticated callers read/write/delete access to those records. Both issues affect the core feature this PR introduces.

src/Migration/Sources/Appwrite.php (null fields in exportApiKeys) and src/Migration/Destinations/Appwrite.php (permissions in createApiKey) need the most attention before merging.

Important Files Changed

Filename Overview
src/Migration/Resources/Integrations/ApiKey.php New resource class for API key migration; constructor correctly provides default values for optional fields, but exportApiKeys in the Source passes SDK fields directly without null-coalescing, which can cause TypeErrors on keys with no expiry or no access history
src/Migration/Sources/Appwrite.php Adds API key reporting and export via the Project SDK service; pagination loop is correctly structured, but SDK fields that can be null are passed directly to the ApiKey constructor which declares them as non-nullable strings
src/Migration/Destinations/Appwrite.php Adds createApiKey to write migrated keys directly to the platform database; generates a fresh random secret (intentional — source secrets are not exportable), but uses Role::any() permissions that grant unauthenticated access to key documents
src/Migration/Resource.php Adds TYPE_API_KEY = 'api-key' constant and registers it in SUPPORTED_RESOURCES; straightforward addition consistent with existing resource type definitions
src/Migration/Transfer.php Registers TYPE_API_KEY in GROUP_INTEGRATIONS_RESOURCES and the resource ordering arrays; consistent with how other integration resources are registered

Reviews (6): Last reviewed commit: "Query keys by resourceInternalId/resourc..." | Re-trigger Greptile

Comment thread src/Migration/Sources/Appwrite.php Outdated
Comment thread src/Migration/Sources/Appwrite.php Outdated
Comment thread src/Migration/Sources/Appwrite.php Outdated
Comment thread src/Migration/Destinations/Appwrite.php Outdated
Source uses Project SDK (listKeys with cursor pagination); destination
writes keys directly via dbForPlatform, matching the platform pattern.
Comment thread src/Migration/Destinations/Appwrite.php
$this->headers/endpoint/key were only read by the inherited call() method
which the destination no longer invokes. STATUS_ERROR is never set inside
createPlatform/createApiKey (they throw), so the guard only needs SKIPPED.
Reverting the wider cleanup — those properties are part of the
inherited Target surface, not the headers issue under review.
Matches the existing platform pattern. Source-side SDK Key model doesn't
expose $permissions today so this is [] in practice (same as platforms),
but the hook is in place for when source can populate it.
SDK strips $permissions from Key responses so we can't copy from source;
match the upstream createKey controller default since dbForPlatform.keys
is gated by endpoint scope, not document perms.
Comment thread src/Migration/Sources/Appwrite.php
Drop the endpoint-scope tangent — the comment is about why we picked
this value, not about whether doc perms get enforced.
projectInternalId is a written-but-not-queryable legacy column on the
keys collection (upstream filter uses resourceInternalId + resourceType).
Mirror that here so the duplicate-check find() doesn't error out.
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.

1 participant