Files
alla-tms/plans/fix-online-lesson-review-note-visibility-report.md
2026-07-16 09:53:14 +07:00

4.4 KiB

Online Lesson Review Note Visibility Fix Report

1. Executive Summary

Fixed the online lesson review note visibility leak by filtering internal workflow fields at the DTO serialization layer and gating the detail UI with a permission-derived capability. General users can still view published lesson content, but they no longer receive or render internal review data such as review comments, reviewer IDs, approval IDs, and workflow timestamps.

2. Problem Found

The online lesson detail page showed the internal review note section when review_comment existed. The same API serializer was used for learner-facing and back-office responses, so public/general users could also receive internal workflow data in network responses.

3. Root Cause

serializeOnlineLesson() always included workflow fields regardless of the current user's permissions. The detail component then rendered review_comment based only on whether the field had a value.

4. Data Flow Before Fix

Database online_lessons.review_comment and workflow actor fields were selected by getBaseSelect(), serialized by serializeOnlineLesson(), returned by /api/online-lessons and /api/online-lessons/[id], cached by TanStack Query, and rendered by OnlineLessonDetailPage.

5. Permission Rule Applied

Internal review data is included only when canReadAllContent('online_lesson', permissions) returns true. This maps to the existing online_lesson:read_all permission and avoids adding new hard-coded role checks.

6. Files Changed

src/features/online-lessons/server/online-lesson-data.ts

  • Added includeInternalReviewData serialization option.
  • Public serialization omits internal workflow fields.
  • List responses now include internal fields only for users with online lesson read-all permission.

src/app/api/online-lessons/[id]/route.ts

  • Detail GET now serializes public or internal DTO based on canReadAllContent.
  • Removed an unused local variable flagged by lint.

src/features/online-lessons/api/types.ts

  • Marked internal workflow fields as optional because public DTOs intentionally omit them.

src/app/dashboard/online-lessons/[id]/page.tsx

  • Computes canViewInternalReviewData on the server from existing permissions and passes it to the client detail component.

src/features/online-lessons/components/online-lesson-detail-page.tsx

  • Renders the review note section only when canViewInternalReviewData is true.
  • Hides creator metadata from the learner-facing detail header.

7. API Changes

For users without online_lesson:read_all, /api/online-lessons and /api/online-lessons/[id] no longer include these internal fields:

  • review_comment
  • submitted_at
  • submitted_by
  • reviewed_at
  • reviewed_by
  • approved_at
  • approved_by
  • published_by
  • created_by
  • created_by_name
  • updated_by
  • updated_by_name

Back-office users with online_lesson:read_all continue to receive these fields.

8. UI Changes

The user-facing detail page no longer displays the review note block for general users. Back-office users with the permission-derived capability can still see review notes in the detail view and form/edit workflow.

9. DTO and Type Changes

The shared OnlineLesson contract now treats internal workflow fields as optional so public DTOs can omit them without sending null placeholders or leaking field names.

10. Test Results

  • npm run lint -- src/features/online-lessons/api/types.ts src/features/online-lessons/server/online-lesson-data.ts src/app/api/online-lessons/[id]/route.ts src/app/dashboard/online-lessons/[id]/page.tsx src/features/online-lessons/components/online-lesson-detail-page.tsx passed.
  • npx tsc --noEmit --pretty false passed.
  • npm run build passed.

11. Security Verification

The protection is enforced server-side before JSON serialization, so general users no longer receive internal review fields in API responses. The UI guard is a second layer and uses a capability computed from the same permission rule.

12. Regression Check

Existing workflow mutations still use the default internal serializer for create/update/audit flows. Review, return, reject, approve, publish, and archive behavior was not changed.

13. Remaining Risks

No automated browser test was added for inspecting the exact network payload. Manual verification should still include logging in as a general user, opening a published lesson, and confirming the response does not include review_comment or workflow actor fields.