Skip to content

Commit 9e8a7e4

Browse files
authored
fix: do not prevent POST /app-manifests/{code}/conversions requests (#30)
BREAKING CHANGE: Mutating requests (`DELETE`, `PATCH`, `POST`, `PUT`) or no longer blocked before sending the request. The response status is handled instead and the error message is amended where applicable
1 parent 2ffa523 commit 9e8a7e4

File tree

5 files changed

+105
-23
lines changed

5 files changed

+105
-23
lines changed

package-lock.json

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@
3333
"@pika/plugin-build-web": "^0.9.0",
3434
"@pika/plugin-ts-standard-pkg": "^0.9.0",
3535
"@tsconfig/node10": "^1.0.3",
36-
"@types/fetch-mock": "^7.3.1",
3736
"@types/jest": "^26.0.0",
38-
"fetch-mock": "^9.0.0",
37+
"fetch-mock": "^9.10.7",
3938
"jest": "^25.1.0",
4039
"semantic-release": "^17.0.0",
4140
"ts-jest": "^25.1.0",

src/hook.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
import { isRateLimitError } from "./is-rate-limit-error";
1212
import { isAbuseLimitError } from "./is-abuse-limit-error";
1313

14-
const MUTATING_METHODS = ["DELETE", "PATCH", "POST", "PUT"];
15-
1614
export async function hook(
1715
reason: string,
1816
request: RequestInterface,
@@ -24,27 +22,32 @@ export async function hook(
2422
parameters
2523
);
2624

27-
if (MUTATING_METHODS.includes(endpoint.method)) {
28-
throw new RequestError(
29-
`"${endpoint.method} ${endpoint.url}" is not permitted due to lack of authentication. Reason: ${reason}`,
30-
403,
31-
{
32-
request: request.endpoint.parse(endpoint),
33-
}
34-
);
35-
}
36-
3725
return request(endpoint as EndpointOptions).catch((error) => {
3826
if (error.status === 404) {
3927
error.message = `Not found. May be due to lack of authentication. Reason: ${reason}`;
28+
throw error;
4029
}
4130

4231
if (isRateLimitError(error)) {
4332
error.message = `API rate limit exceeded. This maybe caused by the lack of authentication. Reason: ${reason}`;
33+
throw error;
4434
}
4535

4636
if (isAbuseLimitError(error)) {
4737
error.message = `You have triggered an abuse detection mechanism. This maybe caused by the lack of authentication. Reason: ${reason}`;
38+
throw error;
39+
}
40+
41+
if (error.status === 401) {
42+
error.message = `Unauthorized. "${endpoint.method} ${endpoint.url}" failed most likely due to lack of authentication. Reason: ${reason}`;
43+
throw error;
44+
}
45+
46+
if (error.status >= 400 && error.status < 500) {
47+
error.message = error.message.replace(
48+
/\.?$/,
49+
`. May be caused by lack of authentication (${reason}).`
50+
);
4851
}
4952

5053
throw error;

test/index.test.ts

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,15 @@ test('auth.hook(request, "GET /repos/octocat/hello-world") returns rate limit re
175175
}
176176
});
177177

178-
test('auth.hook(request, "PATCH /repos/octocat/hello-world") fails without sending request', async () => {
178+
test('auth.hook(request, "PATCH /repos/octocat/hello-world") with 401 response', async () => {
179179
const requestMock = request.defaults({
180180
headers: {
181181
"user-agent": "test",
182182
},
183183
request: {
184-
fetch: fetchMock.sandbox(),
184+
fetch: fetchMock
185+
.sandbox()
186+
.patchOnce("path:/repos/octocat/hello-world", 401),
185187
},
186188
});
187189

@@ -192,7 +194,7 @@ test('auth.hook(request, "PATCH /repos/octocat/hello-world") fails without sendi
192194
throw new Error("should not resolve");
193195
} catch (error) {
194196
expect(error.message).toBe(
195-
'"PATCH /repos/octocat/hello-world" is not permitted due to lack of authentication. Reason: test'
197+
'Unauthorized. "PATCH /repos/octocat/hello-world" failed most likely due to lack of authentication. Reason: test'
196198
);
197199
}
198200
});
@@ -218,3 +220,62 @@ test('auth.hook(request, "GET /repos/octocat/hello-world") does not swallow non-
218220
expect(error.message).toBe("unrelated");
219221
}
220222
});
223+
224+
test('auth.hook(request, "POST /repos/octocat/hello-world/issues/123/comments") with 403 response', async () => {
225+
const requestMock = request.defaults({
226+
headers: {
227+
"user-agent": "test",
228+
},
229+
request: {
230+
fetch: fetchMock
231+
.sandbox()
232+
.postOnce("path:/repos/octocat/hello-world/issues/123/comments", {
233+
status: 403,
234+
body: {
235+
message: "You cannot comment on locked issues",
236+
},
237+
}),
238+
},
239+
});
240+
241+
const { hook } = createUnauthenticatedAuth({ reason: "test" });
242+
243+
try {
244+
await hook(
245+
requestMock,
246+
"POST /repos/octocat/hello-world/issues/123/comments"
247+
);
248+
249+
throw new Error("should not resolve");
250+
} catch (error) {
251+
expect(error.message).toBe(
252+
"You cannot comment on locked issues. May be caused by lack of authentication (test)."
253+
);
254+
}
255+
});
256+
257+
test('500 response', async () => {
258+
const requestMock = request.defaults({
259+
headers: {
260+
"user-agent": "test",
261+
},
262+
request: {
263+
fetch: fetchMock
264+
.sandbox()
265+
.getOnce("path:/", 500),
266+
},
267+
});
268+
269+
const { hook } = createUnauthenticatedAuth({ reason: "test" });
270+
271+
try {
272+
await hook(
273+
requestMock,
274+
"GET /"
275+
);
276+
277+
throw new Error("should not resolve");
278+
} catch (error) {
279+
expect(error.message).toBe("");
280+
}
281+
});

test/issues.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { request } from "@octokit/request";
2+
import fetchMock, { MockMatcherFunction } from "fetch-mock";
3+
4+
import { createUnauthenticatedAuth } from "../src/index";
5+
6+
test('https://github.com/octokit/auth-unauthenticated.js/issues/29', async () => {
7+
const requestMock = request.defaults({
8+
headers: {
9+
"user-agent": "test",
10+
},
11+
request: {
12+
fetch: fetchMock.sandbox().postOnce('path:/app-manifests/123/conversions', {
13+
status: 201,
14+
body: { id: 1}
15+
}),
16+
},
17+
});
18+
19+
const { hook } = createUnauthenticatedAuth({ reason: "test" });
20+
const { data } = await hook(requestMock, "POST /app-manifests/{code}/conversions", {
21+
code: 123
22+
});
23+
24+
expect(data).toStrictEqual({ id: 1 });
25+
});

0 commit comments

Comments
 (0)