Skip to content
This repository has been archived by the owner on Sep 9, 2024. It is now read-only.

Commit

Permalink
feat: Support custom auth schemes for Github API (#1086)
Browse files Browse the repository at this point in the history
  • Loading branch information
soceanainn authored Mar 5, 2024
1 parent dcdc492 commit 17b32f0
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
7 changes: 5 additions & 2 deletions packages/core/src/backends/github/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from '@staticcms/core/lib/util/APIUtils';
import { GitHubCommitStatusState, PullRequestState } from './types';

import type { DataFile, PersistOptions, UnpublishedEntry } from '@staticcms/core';
import type { AuthScheme, DataFile, PersistOptions, UnpublishedEntry } from '@staticcms/core';
import type { ApiRequest, FetchError } from '@staticcms/core/lib/util';
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
import type { Semaphore } from 'semaphore';
Expand Down Expand Up @@ -75,6 +75,7 @@ export const MOCK_PULL_REQUEST = -1;
export interface Config {
apiRoot?: string;
token?: string;
authScheme?: AuthScheme;
branch?: string;
useOpenAuthoring?: boolean;
openAuthoringEnabled?: boolean;
Expand Down Expand Up @@ -162,6 +163,7 @@ export type Diff = {
export default class API {
apiRoot: string;
token: string;
authScheme: AuthScheme;
branch: string;
useOpenAuthoring?: boolean;
openAuthoringEnabled?: boolean;
Expand All @@ -185,6 +187,7 @@ export default class API {
constructor(config: Config) {
this.apiRoot = config.apiRoot || 'https://api.github.com';
this.token = config.token || '';
this.authScheme = config.authScheme || 'token';
this.branch = config.branch || 'main';
this.useOpenAuthoring = config.useOpenAuthoring;
this.repo = config.repo || '';
Expand Down Expand Up @@ -242,7 +245,7 @@ export default class API {
};

if (this.token) {
baseHeader.Authorization = `token ${this.token}`;
baseHeader.Authorization = `${this.authScheme} ${this.token}`;
return Promise.resolve(baseHeader);
}

Expand Down
29 changes: 29 additions & 0 deletions packages/core/src/backends/github/__tests__/API.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,35 @@ describe('github API', () => {
});
});

it('should fetch url with authorization header using custom auth scheme', async () => {
const api = new API({
branch: 'gh-pages',
repo: 'my-repo',
token: 'token',
authScheme: 'Bearer',
squashMerges: false,
initialWorkflowStatus: WorkflowStatus.DRAFT,
cmsLabelPrefix: '',
});

fetch.mockResolvedValue({
text: jest.fn().mockResolvedValue('some response'),
ok: true,
status: 200,
headers: { get: () => '' },
});
const result = await api.request('/some-path');
expect(result).toEqual('some response');
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith('https://api.github.com/some-path', {
cache: 'no-cache',
headers: {
Authorization: 'Bearer token',
'Content-Type': 'application/json; charset=utf-8',
},
});
});

it('should throw error on not ok response', async () => {
const api = new API({
branch: 'gh-pages',
Expand Down
14 changes: 9 additions & 5 deletions packages/core/src/backends/github/implementation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import API, { API_NAME } from './API';
import AuthenticationPage from './AuthenticationPage';

import type {
AuthScheme,
BackendClass,
BackendEntry,
ConfigWithDefaults,
Expand Down Expand Up @@ -75,6 +76,7 @@ export default class GitHub implements BackendClass {
mediaFolder?: string;
previewContext: string;
token: string | null;
authScheme: AuthScheme;
squashMerges: boolean;
cmsLabelPrefix: string;
_currentUserPromise?: Promise<GitHubUser>;
Expand Down Expand Up @@ -114,6 +116,7 @@ export default class GitHub implements BackendClass {
this.branch = config.backend.branch?.trim() || 'main';
this.apiRoot = config.backend.api_root || 'https://api.github.com';
this.token = '';
this.authScheme = config.backend.auth_scheme || 'token';
this.squashMerges = config.backend.squash_merges || false;
this.cmsLabelPrefix = config.backend.cms_label_prefix || '';
this.mediaFolder = config.media_folder;
Expand Down Expand Up @@ -171,7 +174,7 @@ export default class GitHub implements BackendClass {
let repoExists = false;
while (!repoExists) {
repoExists = await fetch(`${this.apiRoot}/repos/${repo}`, {
headers: { Authorization: `token ${token}` },
headers: { Authorization: `${this.authScheme} ${token}` },
})
.then(() => true)
.catch(err => {
Expand All @@ -194,7 +197,7 @@ export default class GitHub implements BackendClass {
if (!this._currentUserPromise) {
this._currentUserPromise = fetch(`${this.apiRoot}/user`, {
headers: {
Authorization: `token ${token}`,
Authorization: `${this.authScheme} ${token}`,
},
}).then(res => res.json());
}
Expand All @@ -215,7 +218,7 @@ export default class GitHub implements BackendClass {
`${this.apiRoot}/repos/${this.originRepo}/collaborators/${username}/permission`,
{
headers: {
Authorization: `token ${token}`,
Authorization: `${this.authScheme} ${token}`,
},
},
)
Expand All @@ -232,7 +235,7 @@ export default class GitHub implements BackendClass {
const repo = await fetch(`${this.apiRoot}/repos/${currentUser.login}/${repoName}`, {
method: 'GET',
headers: {
Authorization: `token ${token}`,
Authorization: `${this.authScheme} ${token}`,
},
}).then(res => res.json());

Expand Down Expand Up @@ -276,7 +279,7 @@ export default class GitHub implements BackendClass {
const fork = await fetch(`${this.apiRoot}/repos/${this.originRepo}/forks`, {
method: 'POST',
headers: {
Authorization: `token ${token}`,
Authorization: `${this.authScheme} ${token}`,
},
}).then(res => res.json());
this.useOpenAuthoring = true;
Expand All @@ -289,6 +292,7 @@ export default class GitHub implements BackendClass {
const apiCtor = API;
this.api = new apiCtor({
token: this.token,
authScheme: this.authScheme,
branch: this.branch,
repo: this.repo,
originRepo: this.originRepo,
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,8 @@ export interface SelectWidgetOptionObject {

export type AuthScope = 'repo' | 'public_repo';

export type AuthScheme = 'token' | 'Bearer';

export type SlugEncoding = 'unicode' | 'ascii';

export type RenderedField<F extends BaseField = UnknownField> = F & {
Expand Down Expand Up @@ -1025,6 +1027,7 @@ export interface Backend {
identity_url?: string;
gateway_url?: string;
auth_scope?: AuthScope;
auth_scheme?: AuthScheme;
commit_messages?: {
create?: string;
update?: string;
Expand Down

0 comments on commit 17b32f0

Please sign in to comment.