diff --git a/src/renderer/__mocks__/state-mocks.ts b/src/renderer/__mocks__/state-mocks.ts index 2baa46299..315050f43 100644 --- a/src/renderer/__mocks__/state-mocks.ts +++ b/src/renderer/__mocks__/state-mocks.ts @@ -15,16 +15,8 @@ import { Theme, type Token, } from '../types'; -import type { EnterpriseAccount } from '../utils/auth/types'; import { Constants } from '../utils/constants'; -export const mockEnterpriseAccounts: EnterpriseAccount[] = [ - { - hostname: 'github.gitify.io' as Hostname, - token: '1234568790' as Token, - }, -]; - export const mockGitifyUser: GitifyUser = { login: 'octocat', name: 'Mona Lisa Octocat', diff --git a/src/renderer/context/App.test.tsx b/src/renderer/context/App.test.tsx index f642a1754..798bf2808 100644 --- a/src/renderer/context/App.test.tsx +++ b/src/renderer/context/App.test.tsx @@ -48,7 +48,7 @@ describe('renderer/context/App.tsx', () => { const unsubscribeNotificationMock = jest.fn(); const mockDefaultState = { - auth: { accounts: [], enterpriseAccounts: [], token: null, user: null }, + auth: { accounts: [] }, settings: mockSettings, }; @@ -278,9 +278,6 @@ describe('renderer/context/App.tsx', () => { expect(saveStateMock).toHaveBeenCalledWith({ auth: { accounts: [], - enterpriseAccounts: [], - token: null, - user: null, } as AuthState, settings: { ...defaultSettings, @@ -319,9 +316,6 @@ describe('renderer/context/App.tsx', () => { expect(saveStateMock).toHaveBeenCalledWith({ auth: { accounts: [], - enterpriseAccounts: [], - token: null, - user: null, } as AuthState, settings: { ...defaultSettings, @@ -354,9 +348,6 @@ describe('renderer/context/App.tsx', () => { expect(saveStateMock).toHaveBeenCalledWith({ auth: { accounts: [], - enterpriseAccounts: [], - token: null, - user: null, } as AuthState, settings: { ...mockSettings, @@ -390,9 +381,6 @@ describe('renderer/context/App.tsx', () => { expect(saveStateMock).toHaveBeenCalledWith({ auth: { accounts: [], - enterpriseAccounts: [], - token: null, - user: null, } as AuthState, settings: defaultSettings, }); diff --git a/src/renderer/context/App.tsx b/src/renderer/context/App.tsx index 3b53c6186..d7d9d9bec 100644 --- a/src/renderer/context/App.tsx +++ b/src/renderer/context/App.tsx @@ -31,7 +31,6 @@ import { } from '../types'; import type { Notification } from '../typesGitHub'; import { headNotifications } from '../utils/api/client'; -import { migrateAuthenticatedAccounts } from '../utils/auth/migration'; import type { LoginOAuthAppOptions, LoginPersonalAccessTokenOptions, @@ -63,9 +62,6 @@ import { zoomPercentageToLevel } from '../utils/zoom'; export const defaultAuth: AuthState = { accounts: [], - token: null, - enterpriseAccounts: [], - user: null, }; const defaultAppearanceSettings: AppearanceSettingsState = { @@ -279,7 +275,6 @@ export const AppProvider = ({ children }: { children: ReactNode }) => { ); const restoreSettings = useCallback(async () => { - await migrateAuthenticatedAccounts(); const existing = loadState(); // Restore settings before accounts to ensure filters are available before fetching notifications diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 4c0243dd1..b37c2f8cd 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -1,11 +1,7 @@ import type { OcticonProps } from '@primer/octicons-react'; import type { FC } from 'react'; import type { Notification, Reason } from './typesGitHub'; -import type { - AuthMethod, - EnterpriseAccount, - PlatformType, -} from './utils/auth/types'; +import type { AuthMethod, PlatformType } from './utils/auth/types'; declare const __brand: unique symbol; @@ -13,18 +9,6 @@ type Brand = { [__brand]: B }; export interface AuthState { accounts: Account[]; - /** - * @deprecated This attribute is deprecated and will be removed in a future release. - */ - token?: Token; - /** - * @deprecated This attribute is deprecated and will be removed in a future release. - */ - enterpriseAccounts?: EnterpriseAccount[]; - /** - * @deprecated This attribute is deprecated and will be removed in a future release. - */ - user?: GitifyUser | null; } export type Branded = T & Brand; diff --git a/src/renderer/utils/auth/migration.test.ts b/src/renderer/utils/auth/migration.test.ts deleted file mode 100644 index b0206edd3..000000000 --- a/src/renderer/utils/auth/migration.test.ts +++ /dev/null @@ -1,164 +0,0 @@ -import axios from 'axios'; -import nock from 'nock'; - -import * as logger from '../../../shared/logger'; -import { mockGitifyUser, mockToken } from '../../__mocks__/state-mocks'; -import type { AuthState, Hostname } from '../../types'; -import { Constants } from '../constants'; -import { - convertAccounts, - hasAccountsToMigrate, - migrateAuthenticatedAccounts, -} from './migration'; - -jest.spyOn(console, 'log').mockImplementation(() => null); - -describe('renderer/utils/auth/migration.ts', () => { - beforeEach(() => { - // axios will default to using the XHR adapter which can't be intercepted - // by nock. So, configure axios to use the node adapter. - axios.defaults.adapter = 'http'; - }); - - describe('migrateAuthenticatedAccounts', () => { - it('migrate and save legacy accounts', async () => { - const logInfoSpy = jest.spyOn(logger, 'logInfo').mockImplementation(); - jest.spyOn(localStorage.__proto__, 'getItem').mockReturnValueOnce( - JSON.stringify({ - auth: { - token: mockToken, - }, - settings: { theme: 'DARK' }, - }), - ); - - nock('https://api.github.com').get('/user').reply(200, mockGitifyUser); - - jest.spyOn(localStorage.__proto__, 'setItem'); - - await migrateAuthenticatedAccounts(); - - expect(localStorage.setItem).toHaveBeenCalledTimes(1); - expect(logInfoSpy).toHaveBeenCalledTimes(2); - }); - }); - - describe('hasAccountsToMigrate', () => { - it('should not migrate if none exist', () => { - expect(hasAccountsToMigrate(null)).toBe(false); - }); - - it('should not migrate if empty', () => { - expect(hasAccountsToMigrate({} as AuthState)).toBe(false); - }); - - it('should migrate if token exist', () => { - expect( - hasAccountsToMigrate({ - token: mockToken, - } as AuthState), - ).toBe(true); - }); - - it('should migrate if token exist', () => { - expect( - hasAccountsToMigrate({ - enterpriseAccounts: [ - { hostname: 'github.gitify.io' as Hostname, token: mockToken }, - ], - } as AuthState), - ).toBe(true); - }); - - it('should not if there are already accounts', () => { - expect( - hasAccountsToMigrate({ - token: mockToken, - enterpriseAccounts: [ - { hostname: 'github.gitify.io' as Hostname, token: mockToken }, - ], - accounts: [{ hostname: 'github.com' as Hostname, token: mockToken }], - } as AuthState), - ).toBe(false); - }); - }); - - describe('convertAccounts', () => { - it('should convert accounts - personal access token only', async () => { - nock('https://api.github.com') - .get('/user') - .reply(200, { ...mockGitifyUser, avatar_url: mockGitifyUser.avatar }); - - const result = await convertAccounts({ - token: mockToken, - user: mockGitifyUser, - } as AuthState); - - expect(result).toEqual([ - { - hostname: Constants.DEFAULT_AUTH_OPTIONS.hostname, - platform: 'GitHub Cloud', - method: 'Personal Access Token', - token: mockToken, - user: mockGitifyUser, - }, - ]); - }); - - it('should convert accounts - oauth app only', async () => { - nock('https://github.gitify.io/api/v3') - .get('/user') - .reply(200, { ...mockGitifyUser, avatar_url: mockGitifyUser.avatar }); - - const result = await convertAccounts({ - enterpriseAccounts: [ - { hostname: 'github.gitify.io' as Hostname, token: mockToken }, - ], - } as AuthState); - - expect(result).toEqual([ - { - hostname: 'github.gitify.io' as Hostname, - platform: 'GitHub Enterprise Server', - method: 'OAuth App', - token: mockToken, - user: mockGitifyUser, - }, - ]); - }); - - it('should convert accounts - combination', async () => { - nock('https://api.github.com') - .get('/user') - .reply(200, { ...mockGitifyUser, avatar_url: mockGitifyUser.avatar }); - nock('https://github.gitify.io/api/v3') - .get('/user') - .reply(200, { ...mockGitifyUser, avatar_url: mockGitifyUser.avatar }); - - const result = await convertAccounts({ - token: mockToken, - user: mockGitifyUser, - enterpriseAccounts: [ - { hostname: 'github.gitify.io' as Hostname, token: mockToken }, - ], - } as AuthState); - - expect(result).toEqual([ - { - hostname: Constants.DEFAULT_AUTH_OPTIONS.hostname, - platform: 'GitHub Cloud', - method: 'Personal Access Token', - token: mockToken, - user: mockGitifyUser, - }, - { - hostname: 'github.gitify.io' as Hostname, - platform: 'GitHub Enterprise Server', - method: 'OAuth App', - token: mockToken, - user: mockGitifyUser, - }, - ]); - }); - }); -}); diff --git a/src/renderer/utils/auth/migration.ts b/src/renderer/utils/auth/migration.ts deleted file mode 100644 index f662ab7a1..000000000 --- a/src/renderer/utils/auth/migration.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { logInfo } from '../../../shared/logger'; -import type { Account, AuthState } from '../../types'; -import { Constants } from '../constants'; -import { loadState, saveState } from '../storage'; -import { getUserData } from './utils'; - -/** - * Migrate authenticated accounts from old data structure to new data structure (v5.7.0+). - * - * @deprecated We plan to remove this migration logic in a future major release. - */ -export async function migrateAuthenticatedAccounts() { - const existing = loadState(); - - if (!hasAccountsToMigrate(existing.auth)) { - return; - } - - logInfo( - 'migrateAuthenticatedAccounts', - 'Commencing authenticated accounts migration', - ); - - const migratedAccounts = await convertAccounts(existing.auth); - - saveState({ - auth: { ...existing.auth, accounts: migratedAccounts }, - settings: existing.settings, - }); - - logInfo( - 'migrateAuthenticatedAccounts', - 'Authenticated accounts migration complete', - ); -} - -export function hasAccountsToMigrate(existingAuthState: AuthState): boolean { - if (!existingAuthState) { - return false; - } - - // Don't attempt migration if there are already accounts in the new structure - if (existingAuthState?.accounts?.length > 0) { - return false; - } - - if ( - existingAuthState?.token || - existingAuthState?.enterpriseAccounts?.length > 0 - ) { - return true; - } - - return false; -} - -export async function convertAccounts( - existingAuthState: AuthState, -): Promise { - const migratedAccounts: Account[] = []; - - if (existingAuthState?.token) { - const user = await getUserData( - existingAuthState.token, - Constants.DEFAULT_AUTH_OPTIONS.hostname, - ); - - migratedAccounts.push({ - hostname: Constants.DEFAULT_AUTH_OPTIONS.hostname, - platform: 'GitHub Cloud', - method: 'Personal Access Token', - token: existingAuthState.token, - user: user, - }); - } - - if (existingAuthState?.enterpriseAccounts) { - for (const legacyEnterpriseAccount of existingAuthState.enterpriseAccounts) { - const user = await getUserData( - legacyEnterpriseAccount.token, - legacyEnterpriseAccount.hostname, - ); - - migratedAccounts.push({ - hostname: legacyEnterpriseAccount.hostname, - platform: 'GitHub Enterprise Server', - method: 'OAuth App', - token: legacyEnterpriseAccount.token, - user: user, - }); - } - } - - return migratedAccounts; -} diff --git a/src/renderer/utils/auth/types.ts b/src/renderer/utils/auth/types.ts index 74cec66f6..c50b68621 100644 --- a/src/renderer/utils/auth/types.ts +++ b/src/renderer/utils/auth/types.ts @@ -31,11 +31,3 @@ export interface AuthTokenResponse { hostname: Hostname; token: Token; } - -/** - * @deprecated This type is deprecated and will be removed in a future release. - */ -export interface EnterpriseAccount { - hostname: Hostname; - token: Token; -} diff --git a/src/renderer/utils/storage.test.ts b/src/renderer/utils/storage.test.ts index f61e892fe..0203a03c6 100644 --- a/src/renderer/utils/storage.test.ts +++ b/src/renderer/utils/storage.test.ts @@ -32,9 +32,6 @@ describe('renderer/utils/storage.ts', () => { user: null, }, ]); - expect(result.auth.token).toBeUndefined(); - expect(result.auth.enterpriseAccounts).toBeUndefined(); - expect(result.auth.user).toBeUndefined(); expect(result.settings.theme).toBe('DARK_DEFAULT'); });