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

Commit d0d4d2e

Browse files
committed
Support custom auth schemes for Github API (needed for proxies)
1 parent 9379d3c commit d0d4d2e

File tree

4 files changed

+46
-7
lines changed

4 files changed

+46
-7
lines changed

packages/core/src/backends/github/API.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
} from '@staticcms/core/lib/util/APIUtils';
3434
import { GitHubCommitStatusState, PullRequestState } from './types';
3535

36-
import type { DataFile, PersistOptions, UnpublishedEntry } from '@staticcms/core';
36+
import type { AuthScheme, DataFile, PersistOptions, UnpublishedEntry } from '@staticcms/core';
3737
import type { ApiRequest, FetchError } from '@staticcms/core/lib/util';
3838
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
3939
import type { Semaphore } from 'semaphore';
@@ -75,6 +75,7 @@ export const MOCK_PULL_REQUEST = -1;
7575
export interface Config {
7676
apiRoot?: string;
7777
token?: string;
78+
authScheme?: AuthScheme;
7879
branch?: string;
7980
useOpenAuthoring?: boolean;
8081
openAuthoringEnabled?: boolean;
@@ -162,6 +163,7 @@ export type Diff = {
162163
export default class API {
163164
apiRoot: string;
164165
token: string;
166+
authScheme: AuthScheme;
165167
branch: string;
166168
useOpenAuthoring?: boolean;
167169
openAuthoringEnabled?: boolean;
@@ -185,6 +187,7 @@ export default class API {
185187
constructor(config: Config) {
186188
this.apiRoot = config.apiRoot || 'https://api.github.com';
187189
this.token = config.token || '';
190+
this.authScheme = config.authScheme || 'token';
188191
this.branch = config.branch || 'main';
189192
this.useOpenAuthoring = config.useOpenAuthoring;
190193
this.repo = config.repo || '';
@@ -242,7 +245,7 @@ export default class API {
242245
};
243246

244247
if (this.token) {
245-
baseHeader.Authorization = `token ${this.token}`;
248+
baseHeader.Authorization = `${this.authScheme} ${this.token}`;
246249
return Promise.resolve(baseHeader);
247250
}
248251

packages/core/src/backends/github/__tests__/API.spec.ts

+29
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,35 @@ describe('github API', () => {
103103
});
104104
});
105105

106+
it('should fetch url with authorization header using custom auth scheme', async () => {
107+
const api = new API({
108+
branch: 'gh-pages',
109+
repo: 'my-repo',
110+
token: 'token',
111+
authScheme: 'Bearer',
112+
squashMerges: false,
113+
initialWorkflowStatus: WorkflowStatus.DRAFT,
114+
cmsLabelPrefix: '',
115+
});
116+
117+
fetch.mockResolvedValue({
118+
text: jest.fn().mockResolvedValue('some response'),
119+
ok: true,
120+
status: 200,
121+
headers: { get: () => '' },
122+
});
123+
const result = await api.request('/some-path');
124+
expect(result).toEqual('some response');
125+
expect(fetch).toHaveBeenCalledTimes(1);
126+
expect(fetch).toHaveBeenCalledWith('https://api.github.com/some-path', {
127+
cache: 'no-cache',
128+
headers: {
129+
Authorization: 'Bearer token',
130+
'Content-Type': 'application/json; charset=utf-8',
131+
},
132+
});
133+
});
134+
106135
it('should throw error on not ok response', async () => {
107136
const api = new API({
108137
branch: 'gh-pages',

packages/core/src/backends/github/implementation.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import API, { API_NAME } from './API';
2525
import AuthenticationPage from './AuthenticationPage';
2626

2727
import type {
28+
AuthScheme,
2829
BackendClass,
2930
BackendEntry,
3031
ConfigWithDefaults,
@@ -75,6 +76,7 @@ export default class GitHub implements BackendClass {
7576
mediaFolder?: string;
7677
previewContext: string;
7778
token: string | null;
79+
authScheme: AuthScheme;
7880
squashMerges: boolean;
7981
cmsLabelPrefix: string;
8082
_currentUserPromise?: Promise<GitHubUser>;
@@ -114,6 +116,7 @@ export default class GitHub implements BackendClass {
114116
this.branch = config.backend.branch?.trim() || 'main';
115117
this.apiRoot = config.backend.api_root || 'https://api.github.com';
116118
this.token = '';
119+
this.authScheme = config.backend.auth_scheme || 'token';
117120
this.squashMerges = config.backend.squash_merges || false;
118121
this.cmsLabelPrefix = config.backend.cms_label_prefix || '';
119122
this.mediaFolder = config.media_folder;
@@ -171,7 +174,7 @@ export default class GitHub implements BackendClass {
171174
let repoExists = false;
172175
while (!repoExists) {
173176
repoExists = await fetch(`${this.apiRoot}/repos/${repo}`, {
174-
headers: { Authorization: `token ${token}` },
177+
headers: { Authorization: `${this.authScheme} ${token}` },
175178
})
176179
.then(() => true)
177180
.catch(err => {
@@ -194,7 +197,7 @@ export default class GitHub implements BackendClass {
194197
if (!this._currentUserPromise) {
195198
this._currentUserPromise = fetch(`${this.apiRoot}/user`, {
196199
headers: {
197-
Authorization: `token ${token}`,
200+
Authorization: `${this.authScheme} ${token}`,
198201
},
199202
}).then(res => res.json());
200203
}
@@ -215,7 +218,7 @@ export default class GitHub implements BackendClass {
215218
`${this.apiRoot}/repos/${this.originRepo}/collaborators/${username}/permission`,
216219
{
217220
headers: {
218-
Authorization: `token ${token}`,
221+
Authorization: `${this.authScheme} ${token}`,
219222
},
220223
},
221224
)
@@ -232,7 +235,7 @@ export default class GitHub implements BackendClass {
232235
const repo = await fetch(`${this.apiRoot}/repos/${currentUser.login}/${repoName}`, {
233236
method: 'GET',
234237
headers: {
235-
Authorization: `token ${token}`,
238+
Authorization: `${this.authScheme} ${token}`,
236239
},
237240
}).then(res => res.json());
238241

@@ -276,7 +279,7 @@ export default class GitHub implements BackendClass {
276279
const fork = await fetch(`${this.apiRoot}/repos/${this.originRepo}/forks`, {
277280
method: 'POST',
278281
headers: {
279-
Authorization: `token ${token}`,
282+
Authorization: `${this.authScheme} ${token}`,
280283
},
281284
}).then(res => res.json());
282285
this.useOpenAuthoring = true;
@@ -289,6 +292,7 @@ export default class GitHub implements BackendClass {
289292
const apiCtor = API;
290293
this.api = new apiCtor({
291294
token: this.token,
295+
authScheme: this.authScheme,
292296
branch: this.branch,
293297
repo: this.repo,
294298
originRepo: this.originRepo,

packages/core/src/interface.ts

+3
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ export interface SelectWidgetOptionObject {
698698

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

701+
export type AuthScheme = 'token' | 'Bearer';
702+
701703
export type SlugEncoding = 'unicode' | 'ascii';
702704

703705
export type RenderedField<F extends BaseField = UnknownField> = F & {
@@ -1025,6 +1027,7 @@ export interface Backend {
10251027
identity_url?: string;
10261028
gateway_url?: string;
10271029
auth_scope?: AuthScope;
1030+
auth_scheme?: AuthScheme;
10281031
commit_messages?: {
10291032
create?: string;
10301033
update?: string;

0 commit comments

Comments
 (0)