Skip to content

Commit f6e10f7

Browse files
committed
make org names case insensitive; add more installation event tests
1 parent fbb1615 commit f6e10f7

File tree

2 files changed

+106
-20
lines changed

2 files changed

+106
-20
lines changed

src/authorizer.ts

+25-17
Original file line numberDiff line numberDiff line change
@@ -63,23 +63,31 @@ export const authorizer = async ({
6363
const lambdaEvent = { "@gh_event": ghEvent, ...payload };
6464
logger("start", lambdaEvent);
6565

66-
if (
67-
ghEvent === "installation" &&
68-
payload.action === "created" &&
69-
!allowedOrgs.includes(payload.installation.account.login)
70-
) {
71-
logger("unauthorized installation created", lambdaEvent);
72-
try {
73-
await deleteInstallation(payload);
74-
return {
75-
msg: "Application was automatically uninstalled from an unauthorized account.",
76-
httpCode: 200,
77-
isAuthorized: false,
78-
};
79-
} catch (error) {
80-
console.error(error);
81-
return UNINSTALL_FAILED_RESPONSE;
66+
allowedOrgs = allowedOrgs.map((org) => org.toLowerCase());
67+
68+
if (ghEvent === "installation" && payload.action === "created") {
69+
if (
70+
!allowedOrgs.includes(payload.installation.account.login.toLowerCase())
71+
) {
72+
logger("unauthorized installation created", lambdaEvent);
73+
try {
74+
await deleteInstallation(payload);
75+
return {
76+
msg: "Application was automatically uninstalled from an unauthorized account.",
77+
httpCode: 200,
78+
isAuthorized: false,
79+
};
80+
} catch (error) {
81+
console.error(error);
82+
return UNINSTALL_FAILED_RESPONSE;
83+
}
8284
}
85+
logger("authorized installation created", lambdaEvent);
86+
return {
87+
msg: "New installation from authorized organization.",
88+
httpCode: 200,
89+
isAuthorized: true,
90+
};
8391
}
8492

8593
const organizationObj = payload.organization;
@@ -96,7 +104,7 @@ export const authorizer = async ({
96104
};
97105
}
98106

99-
if (!allowedOrgs.includes(organizationObj.login)) {
107+
if (!allowedOrgs.includes(organizationObj.login.toLowerCase())) {
100108
logger("unauthorized webhook received", lambdaEvent);
101109

102110
try {

tests/authorizer.test.ts

+81-3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,54 @@ describe("default", () => {
7575
});
7676
});
7777

78+
test("authorized installation created", async () => {
79+
const result = await authorizer({
80+
allowedOrgs: ["rapidsai"],
81+
event: makeInstallationEvent({
82+
action: "created",
83+
orgName: "rapidsai",
84+
}),
85+
});
86+
expect(mockDeleteInstallation).not.toHaveBeenCalled();
87+
expect(result).toStrictEqual({
88+
msg: "New installation from authorized organization.",
89+
httpCode: 200,
90+
isAuthorized: true,
91+
});
92+
});
93+
94+
test("authorized installation created (case insensitive 1)", async () => {
95+
const result = await authorizer({
96+
allowedOrgs: ["RAPIDSAI"],
97+
event: makeInstallationEvent({
98+
action: "created",
99+
orgName: "rapidsai",
100+
}),
101+
});
102+
expect(mockDeleteInstallation).not.toHaveBeenCalled();
103+
expect(result).toStrictEqual({
104+
msg: "New installation from authorized organization.",
105+
httpCode: 200,
106+
isAuthorized: true,
107+
});
108+
});
109+
110+
test("authorized installation created (case insensitive 2)", async () => {
111+
const result = await authorizer({
112+
allowedOrgs: ["rapidsai"],
113+
event: makeInstallationEvent({
114+
action: "created",
115+
orgName: "RAPIDSAI",
116+
}),
117+
});
118+
expect(mockDeleteInstallation).not.toHaveBeenCalled();
119+
expect(result).toStrictEqual({
120+
msg: "New installation from authorized organization.",
121+
httpCode: 200,
122+
isAuthorized: true,
123+
});
124+
});
125+
78126
test("installation deleted (no org object)", async () => {
79127
const result = await authorizer({
80128
allowedOrgs: ["rapidsai"],
@@ -91,7 +139,7 @@ describe("default", () => {
91139
});
92140
});
93141

94-
test("issue_comment created | delete success", async () => {
142+
test("unauthorized org issue_comment | delete success", async () => {
95143
mockDeleteInstallation.mockReturnValueOnce("deleted successfully");
96144
const result = await authorizer({
97145
allowedOrgs: ["rapidsai"],
@@ -106,7 +154,7 @@ describe("default", () => {
106154
});
107155
});
108156

109-
test("issue_comment created | delete failed", async () => {
157+
test("unauthorized org issue_comment | delete failed", async () => {
110158
mockDeleteInstallation.mockRejectedValueOnce("error deleting installation");
111159
const result = await authorizer({
112160
allowedOrgs: ["rapidsai"],
@@ -121,7 +169,7 @@ describe("default", () => {
121169
});
122170
});
123171

124-
test("issue_comment created | delete success", async () => {
172+
test("authorized org issue_comment", async () => {
125173
mockDeleteInstallation.mockReturnValueOnce("deleted successfully");
126174
const result = await authorizer({
127175
allowedOrgs: ["rapidsai"],
@@ -135,4 +183,34 @@ describe("default", () => {
135183
isAuthorized: true,
136184
});
137185
});
186+
187+
test("authorized org issue_comment (case insensitive 1)", async () => {
188+
mockDeleteInstallation.mockReturnValueOnce("deleted successfully");
189+
const result = await authorizer({
190+
allowedOrgs: ["rapidsai"],
191+
event: makeIssueCommentEvent({
192+
orgName: "RAPIDSAI",
193+
}),
194+
});
195+
expect(result).toStrictEqual({
196+
msg: "Organization is authorized.",
197+
httpCode: 200,
198+
isAuthorized: true,
199+
});
200+
});
201+
202+
test("authorized org issue_comment (case insensitive 2)", async () => {
203+
mockDeleteInstallation.mockReturnValueOnce("deleted successfully");
204+
const result = await authorizer({
205+
allowedOrgs: ["RAPIDSAI"],
206+
event: makeIssueCommentEvent({
207+
orgName: "rapidsai",
208+
}),
209+
});
210+
expect(result).toStrictEqual({
211+
msg: "Organization is authorized.",
212+
httpCode: 200,
213+
isAuthorized: true,
214+
});
215+
});
138216
});

0 commit comments

Comments
 (0)