Skip to content

Commit 0660124

Browse files
committed
feat: device code flow
Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent 2c70e48 commit 0660124

12 files changed

Lines changed: 26 additions & 38 deletions

File tree

src/renderer/__mocks__/account-mocks.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const mockGitHubAppAccount: Account = {
1414
platform: 'GitHub Cloud',
1515
method: 'GitHub App',
1616
token: 'token-987654321' as Token,
17-
hostname: Constants.OAUTH_DEVICE_FLOW.hostname,
17+
hostname: Constants.GITHUB_HOSTNAME,
1818
user: mockGitifyUser,
1919
hasRequiredScopes: true,
2020
};
@@ -23,7 +23,7 @@ export const mockPersonalAccessTokenAccount: Account = {
2323
platform: 'GitHub Cloud',
2424
method: 'Personal Access Token',
2525
token: 'token-123-456' as Token,
26-
hostname: 'github.com' as Hostname,
26+
hostname: Constants.GITHUB_HOSTNAME,
2727
user: mockGitifyUser,
2828
hasRequiredScopes: true,
2929
};
@@ -41,7 +41,7 @@ export const mockGitHubCloudAccount: Account = {
4141
platform: 'GitHub Cloud',
4242
method: 'Personal Access Token',
4343
token: 'token-123-456' as Token,
44-
hostname: 'github.com' as Hostname,
44+
hostname: Constants.GITHUB_HOSTNAME,
4545
user: mockGitifyUser,
4646
version: 'latest',
4747
hasRequiredScopes: true,

src/renderer/constants.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { ClientID, Hostname, Link } from './types';
2-
import type { LoginOAuthDeviceOptions } from './utils/auth/types';
32

43
export const Constants = {
54
STORAGE_KEY: 'gitify-storage',
@@ -10,10 +9,9 @@ export const Constants = {
109
ALTERNATE: ['read:user', 'notifications', 'public_repo'],
1110
},
1211

13-
OAUTH_DEVICE_FLOW: {
14-
hostname: 'github.com' as Hostname,
15-
clientId: process.env.OAUTH_CLIENT_ID as ClientID,
16-
} satisfies LoginOAuthDeviceOptions,
12+
GITHUB_HOSTNAME: 'github.com' as Hostname,
13+
14+
OAUTH_DEVICE_FLOW_CLIENT_ID: process.env.OAUTH_CLIENT_ID as ClientID,
1715

1816
// GitHub Enterprise Cloud with Data Residency uses *.ghe.com domains
1917
GITHUB_ENTERPRISE_CLOUD_DATA_RESIDENCY_HOSTNAME: 'ghe.com',

src/renderer/context/App.test.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {
1414
AuthState,
1515
ClientID,
1616
ClientSecret,
17-
Hostname,
1817
SettingsState,
1918
Token,
2019
} from '../types';
@@ -324,7 +323,7 @@ describe('renderer/context/App.tsx', () => {
324323
act(() => {
325324
getContext().loginWithDeviceFlowComplete(
326325
'token' as Token,
327-
'github.com' as Hostname,
326+
Constants.GITHUB_HOSTNAME,
328327
);
329328
});
330329

@@ -348,7 +347,7 @@ describe('renderer/context/App.tsx', () => {
348347
getContext().loginWithOAuthApp({
349348
clientId: 'id' as ClientID,
350349
clientSecret: 'secret' as ClientSecret,
351-
hostname: 'github.com' as Hostname,
350+
hostname: Constants.GITHUB_HOSTNAME,
352351
});
353352
});
354353

src/renderer/context/App.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export interface AppContextState {
8585
) => Promise<Token | null>;
8686
loginWithDeviceFlowComplete: (
8787
token: Token,
88-
hostname?: Hostname,
88+
hostname: Hostname,
8989
) => Promise<void>;
9090
loginWithOAuthApp: (data: LoginOAuthWebOptions) => Promise<void>;
9191
loginWithPersonalAccessToken: (
@@ -433,10 +433,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
433433
* Finalize device flow session.
434434
*/
435435
const loginWithDeviceFlowComplete = useCallback(
436-
async (
437-
token: Token,
438-
hostname: Hostname = Constants.OAUTH_DEVICE_FLOW.hostname,
439-
) => {
436+
async (token: Token, hostname: Hostname) => {
440437
const updatedAuth = await addAccount(auth, 'GitHub App', token, hostname);
441438

442439
persistAuth(updatedAuth);

src/renderer/routes/LoginWithOAuthApp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export const LoginWithOAuthAppRoute: FC = () => {
8585
const [isVerifyingCredentials, setIsVerifyingCredentials] = useState(false);
8686

8787
const [formData, setFormData] = useState({
88-
hostname: 'github.com' as Hostname,
88+
hostname: Constants.GITHUB_HOSTNAME,
8989
clientId: '' as ClientID,
9090
clientSecret: '' as ClientSecret,
9191
} as IFormData);

src/renderer/routes/LoginWithPersonalAccessToken.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const LoginWithPersonalAccessTokenRoute: FC = () => {
7878
const [isVerifyingCredentials, setIsVerifyingCredentials] = useState(false);
7979

8080
const [formData, setFormData] = useState({
81-
hostname: 'github.com' as Hostname,
81+
hostname: Constants.GITHUB_HOSTNAME,
8282
token: '' as Token,
8383
} as IFormData);
8484

src/renderer/utils/api/utils.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
import { Constants } from '../../constants';
2+
13
import type { Hostname } from '../../types';
24

35
import { getGitHubAPIBaseUrl } from './utils';
46

57
describe('renderer/utils/api/utils.ts', () => {
68
describe('getGitHubAPIBaseUrl', () => {
79
it('should generate a GitHub REST API url - non enterprise', () => {
8-
const result = getGitHubAPIBaseUrl('github.com' as Hostname, 'rest');
10+
const result = getGitHubAPIBaseUrl(Constants.GITHUB_HOSTNAME, 'rest');
911

1012
expect(result.toString()).toBe('https://api.github.com/');
1113
});
@@ -27,7 +29,7 @@ describe('renderer/utils/api/utils.ts', () => {
2729
});
2830

2931
it('should generate a GitHub GraphQL url - non enterprise', () => {
30-
const result = getGitHubAPIBaseUrl('github.com' as Hostname, 'graphql');
32+
const result = getGitHubAPIBaseUrl(Constants.GITHUB_HOSTNAME, 'graphql');
3133

3234
expect(result.toString()).toBe('https://api.github.com/');
3335
});

src/renderer/utils/auth/types.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ export type PlatformType =
1313
| 'GitHub Enterprise Server'
1414
| 'GitHub Enterprise Cloud with Data Residency';
1515

16-
export interface LoginOAuthDeviceOptions {
17-
hostname: Hostname;
18-
clientId: ClientID;
19-
}
20-
2116
export interface LoginOAuthWebOptions {
2217
hostname: Hostname;
2318
clientId: ClientID;

src/renderer/utils/auth/utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ describe('renderer/utils/auth/utils.ts', () => {
557557

558558
it('should use default hostname if no accounts', () => {
559559
expect(authUtils.getPrimaryAccountHostname({ accounts: [] })).toBe(
560-
Constants.OAUTH_DEVICE_FLOW.hostname,
560+
Constants.GITHUB_HOSTNAME,
561561
);
562562
});
563563
});

src/renderer/utils/auth/utils.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import type {
2929
AuthResponse,
3030
DeviceFlowErrorResponse,
3131
DeviceFlowSession,
32-
LoginOAuthDeviceOptions,
3332
LoginOAuthWebOptions,
3433
} from './types';
3534

@@ -88,21 +87,19 @@ export function performGitHubWebOAuth(
8887
});
8988
}
9089

91-
export async function startGitHubDeviceFlow(
92-
authOptions: LoginOAuthDeviceOptions = Constants.OAUTH_DEVICE_FLOW,
93-
): Promise<DeviceFlowSession> {
90+
export async function startGitHubDeviceFlow(): Promise<DeviceFlowSession> {
9491
const deviceCode = await createDeviceCode({
9592
clientType: 'oauth-app' as const,
96-
clientId: authOptions.clientId,
93+
clientId: Constants.OAUTH_DEVICE_FLOW_CLIENT_ID,
9794
scopes: Constants.OAUTH_SCOPES.RECOMMENDED,
9895
request: request.defaults({
99-
baseUrl: getGitHubAuthBaseUrl(authOptions.hostname).toString(),
96+
baseUrl: getGitHubAuthBaseUrl(Constants.GITHUB_HOSTNAME).toString(),
10097
}),
10198
});
10299

103100
return {
104-
hostname: authOptions.hostname,
105-
clientId: authOptions.clientId,
101+
hostname: Constants.GITHUB_HOSTNAME,
102+
clientId: Constants.OAUTH_DEVICE_FLOW_CLIENT_ID,
106103
deviceCode: deviceCode.data.device_code,
107104
userCode: deviceCode.data.user_code,
108105
verificationUri: deviceCode.data.verification_uri,
@@ -391,7 +388,7 @@ export function getAccountUUID(account: Account): AccountUUID {
391388
* Return the primary (first) account hostname
392389
*/
393390
export function getPrimaryAccountHostname(auth: AuthState) {
394-
return auth.accounts[0]?.hostname ?? Constants.OAUTH_DEVICE_FLOW.hostname;
391+
return auth.accounts[0]?.hostname ?? Constants.GITHUB_HOSTNAME;
395392
}
396393

397394
export function hasAccounts(auth: AuthState) {

0 commit comments

Comments
 (0)