Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions src/libs/actions/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ function editTaskAssignee(report: OnyxTypes.Report, sessionAccountID: number, as
const assigneeChatReportID = assigneeChatReport?.reportID;
const assigneeChatReportMetadata = ReportUtils.getReportMetadata(assigneeChatReportID);
const parentReport = getParentReport(report);
const taskOwnerAccountID = getTaskOwnerAccountID(report);
const taskOwnerAccountID = report?.ownerAccountID;
const optimisticReport: OptimisticReport = {
reportName,
managerID: assigneeAccountID ?? report.managerID,
Expand Down Expand Up @@ -1209,17 +1209,10 @@ function getTaskAssigneeAccountID(taskReport: OnyxEntry<OnyxTypes.Report>): numb
return reportAction?.childManagerAccountID;
}

/**
* Returns Task owner accountID
*/
function getTaskOwnerAccountID(taskReport: OnyxEntry<OnyxTypes.Report>): number | undefined {
return taskReport?.ownerAccountID;
}

/**
* Check if you're allowed to modify the task - only the author can modify the task
*/
function canModifyTask(taskReport: OnyxEntry<OnyxTypes.Report>, sessionAccountID: number, taskOwnerAccountID?: number, isParentReportArchived = false): boolean {
function canModifyTask(taskReport: OnyxEntry<OnyxTypes.Report>, sessionAccountID: number, isParentReportArchived = false): boolean {
if (ReportUtils.isCanceledTaskReport(taskReport)) {
return false;
}
Expand All @@ -1228,8 +1221,7 @@ function canModifyTask(taskReport: OnyxEntry<OnyxTypes.Report>, sessionAccountID
return false;
}

const ownerAccountID = getTaskOwnerAccountID(taskReport) ?? taskOwnerAccountID;
return sessionAccountID === ownerAccountID;
return sessionAccountID === taskReport?.ownerAccountID;
}

/**
Expand All @@ -1249,7 +1241,7 @@ function canActionTask(taskReport: OnyxEntry<OnyxTypes.Report>, sessionAccountID
return false;
}

const ownerAccountID = getTaskOwnerAccountID(taskReport) ?? taskOwnerAccountID;
const ownerAccountID = taskReport?.ownerAccountID ?? taskOwnerAccountID;
const assigneeAccountID = getTaskAssigneeAccountID(taskReport) ?? taskAssigneeAccountID;
return sessionAccountID === ownerAccountID || sessionAccountID === assigneeAccountID;
}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Search/EmptySearchView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function EmptySearchView({type, hasResults}: EmptySearchViewProps) {
const [viewTourTaskReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${viewTourTaskReportID}`, {canBeMissing: false});
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const isReportArchived = useReportIsArchived(viewTourTaskReport?.parentReportID);
const canModifyTheTask = canModifyTask(viewTourTaskReport, currentUserPersonalDetails.accountID, undefined, isReportArchived);
const canModifyTheTask = canModifyTask(viewTourTaskReport, currentUserPersonalDetails.accountID, isReportArchived);
const canActionTheTask = canActionTask(viewTourTaskReport, currentUserPersonalDetails.accountID);

const content = useMemo(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/tasks/TaskAssigneeSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ function TaskAssigneeSelectorModal() {

const isOpen = isOpenTaskReport(report);
const isReportArchived = useReportIsArchived(report?.parentReportID);
const canModifyTaskValue = canModifyTask(report, currentUserPersonalDetails.accountID, undefined, isReportArchived);
const canModifyTaskValue = canModifyTask(report, currentUserPersonalDetails.accountID, isReportArchived);
const isTaskNonEditable = isTaskReport(report) && (!canModifyTaskValue || !isOpen);

useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/tasks/TaskDescriptionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti
const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);

const isOpen = isOpenTaskReport(report);
const isReportArchived = useReportIsArchived(report?.reportID);
const canActuallyModifyTask = canModifyTask(report, currentUserPersonalDetails.accountID, undefined, isReportArchived);
const isReportArchived = useReportIsArchived(report?.parentReportID);
const canActuallyModifyTask = canModifyTask(report, currentUserPersonalDetails.accountID, isReportArchived);
const isTaskNonEditable = isTaskReport(report) && (!canActuallyModifyTask || !isOpen);

useFocusEffect(
Expand Down
41 changes: 29 additions & 12 deletions tests/actions/TaskTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,63 @@ describe('actions/Task', () => {
describe('canModifyTask', () => {
const managerAccountID = 1;
const employeeAccountID = 2;

// Report with a non-archived parent
const report = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);
const archivedReport = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);
const reportParent = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);

// Cancelled report with a non-archived parent
const cancelledTaskReport = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);
const cancelledTaskReportParent = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);

// Report with an archived parent
const reportArchived = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);
const reportArchivedParent = LHNTestUtils.getFakeReport([managerAccountID, employeeAccountID]);

// Set the manager as the owner of each report
report.ownerAccountID = managerAccountID;
archivedReport.ownerAccountID = managerAccountID;
cancelledTaskReport.ownerAccountID = managerAccountID;
reportArchived.ownerAccountID = managerAccountID;

// Set the parent report ID of each report
report.parentReportID = reportParent.reportID;
cancelledTaskReport.parentReportID = cancelledTaskReportParent.reportID;
reportArchived.parentReportID = reportArchivedParent.reportID;

// This is what indicates that the report is a cancelled task report (see ReportUtils.isCanceledTaskReport())
cancelledTaskReport.isDeletedParentAction = true;

beforeAll(async () => {
// Store all the necessary data in Onyx
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${archivedReport.reportID}`, archivedReport);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportParent.reportID}`, reportParent);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${cancelledTaskReport.reportID}`, cancelledTaskReport);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${cancelledTaskReportParent.reportID}`, cancelledTaskReportParent);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportArchived.reportID}`, reportArchived);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportArchivedParent.reportID}`, reportArchivedParent);

// This is what indicates that a report is archived (see ReportUtils.isArchivedReport())
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${archivedReport.reportID}`, {
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportArchivedParent.reportID}`, {
private_isArchived: new Date().toString(),
});
});

it('returns false if the user modifying the task is not the author', () => {
// Simulate how components call canModifyTask() by using the hook useReportIsArchived() to see if the report is archived
const {result: isReportArchived} = renderHook(() => useReportIsArchived(report?.reportID));
expect(canModifyTask(report, employeeAccountID, undefined, isReportArchived.current)).toBe(false);
const {result: isReportArchived} = renderHook(() => useReportIsArchived(report?.parentReportID));
expect(canModifyTask(report, employeeAccountID, isReportArchived.current)).toBe(false);
});
it('returns false if the parent report is archived', () => {
const {result: isReportArchived} = renderHook(() => useReportIsArchived(archivedReport?.reportID));
expect(canModifyTask(archivedReport, managerAccountID, undefined, isReportArchived.current)).toBe(false);
const {result: isReportArchived} = renderHook(() => useReportIsArchived(reportArchived?.parentReportID));
expect(canModifyTask(reportArchived, managerAccountID, isReportArchived.current)).toBe(false);
});
it('returns false if the report is a cancelled task report', () => {
const {result: isReportArchived} = renderHook(() => useReportIsArchived(cancelledTaskReport?.reportID));
expect(canModifyTask(cancelledTaskReport, managerAccountID, undefined, isReportArchived.current)).toBe(false);
const {result: isReportArchived} = renderHook(() => useReportIsArchived(cancelledTaskReport?.parentReportID));
expect(canModifyTask(cancelledTaskReport, managerAccountID, isReportArchived.current)).toBe(false);
});
it('returns true if the user modifying the task is the author and the parent report is not archived or cancelled', () => {
const {result: isReportArchived} = renderHook(() => useReportIsArchived(report?.reportID));
expect(canModifyTask(report, managerAccountID, undefined, isReportArchived.current)).toBe(true);
const {result: isReportArchived} = renderHook(() => useReportIsArchived(report?.parentReportID));
expect(canModifyTask(report, managerAccountID, isReportArchived.current)).toBe(true);
});
});
});