diff --git a/packages/insomnia/src/sync/vcs/migrate-projects-into-organization.ts b/packages/insomnia/src/sync/vcs/migrate-projects-into-organization.ts index 8d3101ba11..9257d2e311 100644 --- a/packages/insomnia/src/sync/vcs/migrate-projects-into-organization.ts +++ b/packages/insomnia/src/sync/vcs/migrate-projects-into-organization.ts @@ -1,15 +1,7 @@ -import { getAccountId, getCurrentSessionId } from '../../account/session'; import { database } from '../../common/database'; import * as models from '../../models'; -import { isOwnerOfOrganization, isPersonalOrganization } from '../../models/organization'; +import { Organization } from '../../models/organization'; import { Project, RemoteProject } from '../../models/project'; -import { OrganizationsResponse } from '../../ui/routes/organization'; -import { invariant } from '../../utils/invariant'; - -let status: 'idle' | 'pending' | 'error' | 'completed' = 'idle'; - -// TODO: -// Error handling and return type for errors // Migration: // Team ~= Project > Workspaces @@ -18,6 +10,12 @@ let status: 'idle' | 'pending' | 'error' | 'completed' = 'idle'; // Organization > TeamProject > Workspaces // In the new API: { _id: 'proj_team_123', remoteId: 'proj_team_123', parentId: 'team_123' } +// the remote id field previously tracked "team_id" +// (remote concept for matching 1:1 with this project) which is now org_id +// the _id field previously tracked the "proj_team_id" +// which was a wrapper for the team_id prefixing proj_to the above id, +// which is now the remoteId for tracking the projects within an org + export const shouldMigrateProjectUnderOrganization = async () => { const localProjectCount = await database.count(models.project.type, { remoteId: null, @@ -33,92 +31,35 @@ export const shouldMigrateProjectUnderOrganization = async () => { return localProjectCount > 0 || legacyRemoteProjectCount > 0; }; -export const migrateProjectsIntoOrganization = async () => { - if (status !== 'idle' && status !== 'error') { - return; +export const migrateProjectsIntoOrganization = async ({ + personalOrganization, +}: { + personalOrganization: Organization; + }) => { + // Legacy remote projects without organizations + const legacyRemoteProjects = await database.find(models.project.type, { + remoteId: { $ne: null }, + parentId: null, + }); + // Legacy remoteId should be orgId and legacy _id should be remoteId + for (const remoteProject of legacyRemoteProjects) { + await models.project.update(remoteProject, { + parentId: remoteProject.remoteId, + remoteId: remoteProject._id, + }); } - status = 'pending'; + // Local projects without organizations except scratchpad + const localProjects = await database.find(models.project.type, { + remoteId: null, + parentId: null, + _id: { $ne: models.project.SCRATCHPAD_PROJECT_ID }, + }); - try { - const sessionId = getCurrentSessionId(); - invariant(sessionId, 'User must be logged in to migrate projects'); - - // local projects what if they dont have a parentId? - // after migration: all projects have a parentId - - // no more hostage projects - // when will we know what org is you have? - // already migrated: all things are globes - // already migrated with a blank account what happens to previous account data? - // go to whatever - - // about to migrate: have one or more projects without parentIds/null - // if the project doesn't have remoteId we can throw in the home org - // if the project has a remoteId, and is in the org, we know it should have org as a parentId - // if the project has a remoteId, and is not in my logged in org - // go to the whatever - - // whatever - // export all - // 1. show a alert describing the state of the orphaned projects and instructing export all and reimport - // 2. show a recovery ux to move old workspaces into existing projects - // 3. show orphaned projects in the home organization - // 4. show disabled orgs in the sidebar from previous account where you can see the data - - // todo - // 1. [x] only assign parentIds and migrate old remote logic - // 2. count orphaned projects - // 3. decide which approach take for orphaned projects - // 4. decide if theres no reason to keep migrateCollectionsIntoRemoteProject - - // assign remote project parentIds to new organization structure - // the remote id field used to track team_id (remote concept for matching 1:1 with this project) which is now org_id - // the _id field used to track the proj_team_id which was a wrapper for the team_id prefixing proj_to the above id, - // which is now the remoteId for tracking the projects within an org - const legacyRemoteProjects = await database.find(models.project.type, { - remoteId: { $ne: null }, - parentId: null, + // Assign all local projects to personal organization + for (const localProject of localProjects) { + await models.project.update(localProject, { + parentId: personalOrganization.id, }); - for (const remoteProject of legacyRemoteProjects) { - await models.project.update(remoteProject, { - parentId: remoteProject.remoteId, - remoteId: remoteProject._id, - }); - } - - // Local projects without organizations except scratchpad - const localProjects = await database.find(models.project.type, { - remoteId: null, - parentId: null, - _id: { $ne: models.project.SCRATCHPAD_PROJECT_ID }, - }); - const organizationsResult = await window.main.insomniaFetch({ - method: 'GET', - path: '/v1/organizations', - sessionId, - }); - const accountId = getAccountId(); - invariant(organizationsResult, 'Failed to fetch organizations'); - invariant(accountId, 'Failed to get account id'); - const { organizations } = organizationsResult; - const personalOrganization = organizations.filter(isPersonalOrganization) - .find(organization => - isOwnerOfOrganization({ - organization, - accountId, - })); - invariant(personalOrganization, 'Failed to find personal organization'); - - for (const localProject of localProjects) { - await models.project.update(localProject, { - parentId: personalOrganization.id, - }); - } - - status = 'completed'; - } catch (err) { - console.warn('Failed to migrate projects to personal workspace', err); - throw err; } }; diff --git a/packages/insomnia/src/ui/index.tsx b/packages/insomnia/src/ui/index.tsx index 780fa7b1ec..6916798ad8 100644 --- a/packages/insomnia/src/ui/index.tsx +++ b/packages/insomnia/src/ui/index.tsx @@ -29,10 +29,8 @@ import { AppLoadingIndicator } from './components/app-loading-indicator'; import Auth from './routes/auth'; import Authorize from './routes/auth.authorize'; import Login from './routes/auth.login'; -import { Migrate } from './routes/auth.migrate'; import { ErrorRoute } from './routes/error'; import Onboarding from './routes/onboarding'; -import { OnboardingCloudMigration } from './routes/onboarding.cloud-migration'; import { shouldOrganizationsRevalidate } from './routes/organization'; import Root from './routes/root'; import { initializeSentry } from './sentry'; @@ -121,12 +119,6 @@ const router = createMemoryRouter( path: 'onboarding/*', element: , }, - { - path: 'onboarding/cloud-migration', - loader: async (...args) => (await import('./routes/onboarding.cloud-migration')).loader(...args), - action: async (...args) => (await import('./routes/onboarding.cloud-migration')).action(...args), - element: , - }, { path: 'import', children: [ @@ -880,7 +872,6 @@ const router = createMemoryRouter( children: [ { path: 'login', - loader: async (...args) => (await import('./routes/auth.login')).loader(...args), action: async (...args) => (await import('./routes/auth.login')).action(...args), element: , }, @@ -893,12 +884,6 @@ const router = createMemoryRouter( action: async (...args) => (await import('./routes/auth.authorize')).action(...args), element: , }, - { - path: 'migrate', - loader: async (...args) => (await import('./routes/auth.migrate')).loader(...args), - action: async (...args) => (await import('./routes/auth.migrate')).action(...args), - element: , - }, ], }, ], diff --git a/packages/insomnia/src/ui/routes/auth.authorize.tsx b/packages/insomnia/src/ui/routes/auth.authorize.tsx index 518d3d9583..5eec87988d 100644 --- a/packages/insomnia/src/ui/routes/auth.authorize.tsx +++ b/packages/insomnia/src/ui/routes/auth.authorize.tsx @@ -2,8 +2,6 @@ import React, { Fragment } from 'react'; import { Heading } from 'react-aria-components'; import { ActionFunction, redirect, useFetcher, useFetchers, useNavigate } from 'react-router-dom'; -import { isLoggedIn } from '../../account/session'; -import { shouldMigrateProjectUnderOrganization } from '../../sync/vcs/migrate-projects-into-organization'; import { invariant } from '../../utils/invariant'; import { getLoginUrl, submitAuthCode } from '../auth-session-provider'; import { Icon } from '../components/icon'; @@ -26,10 +24,6 @@ export const action: ActionFunction = async ({ console.log('Login successful'); window.localStorage.setItem('hasUserLoggedInBefore', 'true'); - if (isLoggedIn() && await shouldMigrateProjectUnderOrganization()) { - throw redirect('/auth/migrate'); - } - return redirect('/organization'); }; @@ -131,7 +125,7 @@ const Authorize = () => { }} disabled={isAuthenticating} > -