Skip to content

Commit f30e9ea

Browse files
fix: address feedback on PR #366
1 parent e118576 commit f30e9ea

File tree

2 files changed

+92
-22
lines changed

2 files changed

+92
-22
lines changed

.github/workflows/pr-agent.yml

Lines changed: 91 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,98 @@ on:
44
types: [opened, reopened, ready_for_review]
55
issue_comment:
66
jobs:
7+
authorize_actor:
8+
if: ${{ github.event.sender.type != 'Bot' }}
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
issues: read
13+
pull-requests: read
14+
outputs:
15+
allowed: ${{ steps.authorize.outputs.allowed }}
16+
steps:
17+
- name: Check triggering actor authorization
18+
id: authorize
19+
uses: actions/github-script@v7
20+
with:
21+
script: |
22+
const allowedAssociations = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
23+
const { owner, repo } = context.repo;
24+
const actor = context.actor;
25+
const eventName = context.eventName;
26+
const payload = context.payload;
27+
28+
const setAllowed = (value, reason) => {
29+
core.setOutput('allowed', value ? 'true' : 'false');
30+
core.info(reason);
31+
};
32+
33+
if (eventName === 'issue_comment') {
34+
if (!payload.issue?.pull_request) {
35+
return setAllowed(false, 'Ignoring issue_comment event that is not tied to a pull request.');
36+
}
37+
38+
const association = payload.comment?.author_association ?? 'NONE';
39+
return setAllowed(
40+
allowedAssociations.has(association),
41+
`Issue comment actor ${actor} has author_association=${association}.`,
42+
);
43+
}
44+
45+
if (eventName !== 'pull_request') {
46+
return setAllowed(false, `Unsupported event: ${eventName}`);
47+
}
48+
49+
if (actor === owner) {
50+
return setAllowed(true, `Actor ${actor} is the repository owner.`);
51+
}
52+
53+
if (payload.repository?.owner?.type === 'Organization') {
54+
try {
55+
const membership = await github.graphql(
56+
`query($organization: String!, $login: String!) {
57+
organization(login: $organization) {
58+
member(login: $login) {
59+
login
60+
}
61+
}
62+
}`,
63+
{
64+
organization: owner,
65+
login: actor,
66+
},
67+
);
68+
69+
if (membership.organization?.member?.login) {
70+
return setAllowed(true, `Actor ${actor} is a member of organization ${owner}.`);
71+
}
72+
} catch (error) {
73+
core.warning(`Organization membership lookup failed for ${actor}: ${error.message}`);
74+
}
75+
}
76+
77+
try {
78+
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
79+
owner,
80+
repo,
81+
username: actor,
82+
});
83+
84+
return setAllowed(
85+
Boolean(data.permission && data.permission !== 'none'),
86+
`Actor ${actor} collaborator permission=${data.permission ?? 'none'}, role=${data.role_name ?? 'unknown'}.`,
87+
);
88+
} catch (error) {
89+
if (error.status === 404) {
90+
return setAllowed(false, `Actor ${actor} is not a collaborator on ${owner}/${repo}.`);
91+
}
92+
93+
throw error;
94+
}
95+
796
pr_agent_job:
8-
if: >-
9-
${{
10-
github.event.sender.type != 'Bot' &&
11-
(
12-
(
13-
github.event_name == 'pull_request' &&
14-
contains(
15-
fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
16-
github.event.pull_request.author_association
17-
)
18-
) ||
19-
(
20-
github.event_name == 'issue_comment' &&
21-
github.event.issue.pull_request &&
22-
contains(
23-
fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
24-
github.event.comment.author_association
25-
)
26-
)
27-
)
28-
}}
97+
needs: authorize_actor
98+
if: ${{ needs.authorize_actor.outputs.allowed == 'true' }}
2999
runs-on: ubuntu-latest
30100
permissions:
31101
issues: write

web/src/components/auth/admin-route.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function AdminRoute({ children }: AdminRouteProps) {
1919
);
2020
}
2121

22-
if (authEnabled && user.role !== 'admin') {
22+
if (authEnabled && user?.role !== 'admin') {
2323
return <Navigate to="/" replace />;
2424
}
2525

0 commit comments

Comments
 (0)