diff --git a/src/handlers/shared/start.ts b/src/handlers/shared/start.ts index 8433e5b..c517d87 100644 --- a/src/handlers/shared/start.ts +++ b/src/handlers/shared/start.ts @@ -1,4 +1,5 @@ import { Context, ISSUE_TYPE, Label } from "../../types"; +import { isUserCollaborator } from "../../utils/get-user-association"; import { addAssignees, addCommentToIssue, getAssignedIssues, getAvailableOpenedPullRequests, getTimeValue, isParentIssue } from "../../utils/issue"; import { HttpStatusCode, Result } from "../result-types"; import { hasUserBeenUnassigned } from "./check-assignments"; @@ -82,7 +83,6 @@ export async function start( throw logger.error(error, { issueNumber: issue.number }); } - // get labels const labels = issue.labels ?? []; const priceLabel = labels.find((label: Label) => label.name.startsWith("Price: ")); @@ -90,6 +90,19 @@ export async function start( throw logger.error("No price label is set to calculate the duration", { issueNumber: issue.number }); } + // Checks if non-collaborators can be assigned to the issue + for (const label of labels) { + if (label.description?.includes("collaborator only")) { + for (const user of toAssign) { + if (!(await isUserCollaborator(context, user))) { + throw logger.error("Non-collaborators cannot be assigned to this issue", { + username: user, + }); + } + } + } + } + const deadline = getDeadline(labels); const toAssignIds = await fetchUserIds(context, toAssign); diff --git a/src/utils/get-user-association.ts b/src/utils/get-user-association.ts new file mode 100644 index 0000000..b626ef2 --- /dev/null +++ b/src/utils/get-user-association.ts @@ -0,0 +1,9 @@ +import { Context } from "../types"; + +export async function isUserCollaborator(context: Context, username: string): Promise { + const { data } = await context.octokit.rest.orgs.getMembershipForUser({ + org: context.payload.repository.owner.login, + username, + }); + return ["collaborator", "member", "admin"].includes(data.role); +}