Skip to content

enhance: ensure that only assessment course participants can access assessment live quizzes#4911

Merged
sjschlapbach merged 3 commits into
v3-assessmentfrom
unauthorized-assessment-redirects
Sep 14, 2025
Merged

enhance: ensure that only assessment course participants can access assessment live quizzes#4911
sjschlapbach merged 3 commits into
v3-assessmentfrom
unauthorized-assessment-redirects

Conversation

@sjschlapbach
Copy link
Copy Markdown
Member

@sjschlapbach sjschlapbach commented Sep 14, 2025

Summary by CodeRabbit

  • New Features
    • Assessment live quizzes now require sign-in and course participation; unauthorized users are redirected to login, and missing participation triggers an in-app error message.
    • Participant authorization is forwarded for live-quiz data fetching to improve access control.
    • Added English and German messages for assessment participation errors and an “Edu-ID” label.
  • Bug Fixes
    • The audience-view link in the cockpit is hidden during assessment mode to prevent unintended access.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 14, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds EDUID login scope (Prisma enum + migration), sets participant JWT scope to EDUID, enforces assessment authentication and course participation in live quizzes, updates PWA session SSR to forward participant token and use APP_ORIGIN_* redirects with new error-driven redirects, shows a toast for missing participation, hides audience cockpit in assessment mode, and removes JWT_ISSUER_* from turbo globalEnv.

Changes

Cohort / File(s) Summary
Auth participant JWT scope
apps/auth/src/pages/api/auth/[...nextauth].ts
Set participant token.scope to UserLoginScope.EDUID (enum) instead of string literal.
Prisma enum + migration
packages/prisma/src/prisma/schema/user.prisma, packages/prisma/src/prisma/schema/migrations/.../migration.sql
Added EDUID variant to enum UserLoginScope; SQL migration adds 'EDUID' to PostgreSQL enum.
GraphQL assessment enforcement
packages/graphql/src/services/liveQuizzes.ts
For assessment quizzes: require participant logged-in with EDUID scope; if missing, throw UNAUTHORIZED_ASSESSMENT; if quiz has courseId, verify participation via Prisma and throw MISSING_ASSESSMENT_COURSE_PARTICIPATION when absent.
PWA session SSR auth and redirects
apps/frontend-pwa/src/pages/session/[id].tsx
getServerSideProps forwards next-auth.participant-session-token as Authorization: Bearer <token>; replaced issuer-based host checks with APP_ORIGIN_*; added redirects for UNAUTHORIZED_ASSESSMENT (to assessment login) and MISSING_ASSESSMENT_COURSE_PARTICIPATION (to assessment PWA with ?error=...); enforce host based on isAssessmentEnabled.
PWA index error toast
apps/frontend-pwa/src/pages/index.tsx
On router.query.error === 'missing_assessment_course_participation' show error toast and remove query param via shallow router.replace.
Manage cockpit assessment guard
apps/frontend-manage/src/components/liveQuiz/cockpit/LiveQuizTimeline.tsx
Render audience-view cockpit link only when assessmentMode === false; added TODO about owner access vs response-api.
Backend JWT middleware comment
apps/backend-docker/src/app.ts
Added non-functional comment above token extraction: // ! DO NOT TOUCH - assessment live quiz mode relies on it.
i18n additions
packages/i18n/messages/en.ts, packages/i18n/messages/de.ts
Added missingAssessmentCourseParticipation message (EN/DE) and EDUID label (manage.*).
Build config env cleanup
turbo.json
Removed JWT_ISSUER_* entries from globalEnv; reordered VAPID keys.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as Participant Browser
  participant PWA as PWA /session/[id].tsx (SSR)
  participant Auth as Cookies
  participant GQL as GraphQL API
  participant Svc as LiveQuizzes Service

  User->>PWA: GET /session/:id
  PWA->>Auth: Read cookie next-auth.participant-session-token
  Note right of PWA: If present, add Authorization: Bearer <token>
  PWA->>GQL: Query GetRunningLiveQuiz (with/without Bearer)
  GQL->>Svc: getRunningLiveQuiz()
  alt Assessment quiz
    Svc->>Svc: Check user role=PARTICIPANT & scope=EDUID
    alt Missing/invalid
      Svc-->>GQL: Error UNAUTHORIZED_ASSESSMENT (FORBIDDEN)
      GQL-->>PWA: GraphQL error
      PWA-->>User: Redirect to APP_ORIGIN_ASSESSMENT_PWA login?redirect_to=<current>
    else Has courseId
      Svc->>Svc: Verify course participation (Prisma)
      alt Not a participant
        Svc-->>GQL: Error MISSING_ASSESSMENT_COURSE_PARTICIPATION
        GQL-->>PWA: GraphQL error
        PWA-->>User: Redirect to APP_ORIGIN_ASSESSMENT_PWA?error=missing_assessment_course_participation
      else Participant ok
        Svc-->>GQL: Quiz data
        GQL-->>PWA: Quiz data
        PWA->>PWA: Enforce host APP_ORIGIN_ASSESSMENT_PWA
        PWA-->>User: Redirect if host mismatch else render
      end
    end
  else Non-assessment quiz
    Svc-->>GQL: Quiz data
    GQL-->>PWA: Quiz data
    PWA->>PWA: Enforce host APP_ORIGIN_PWA
    PWA-->>User: Redirect if host mismatch else render
  end
Loading
sequenceDiagram
  autonumber
  actor User as Participant Browser
  participant PWAHome as PWA /
  Note over PWAHome: On mount
  User->>PWAHome: Navigate with ?error=missing_assessment_course_participation
  PWAHome->>PWAHome: Show toast t('pwa.assessment.missingAssessmentCourseParticipation') for 7000ms
  PWAHome->>PWAHome: router.replace (remove error, shallow)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

size:M

Suggested reviewers

  • rschlaefli

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc10d8 and 58ef0a3.

⛔ Files ignored due to path filters (3)
  • packages/graphql/src/ops.schema.json is excluded by !**/**/ops.schema.json
  • packages/graphql/src/ops.ts is excluded by !**/**/ops.ts
  • packages/graphql/src/public/schema.graphql is excluded by !**/**/public/**
📒 Files selected for processing (11)
  • apps/auth/src/pages/api/auth/[...nextauth].ts (1 hunks)
  • apps/backend-docker/src/app.ts (1 hunks)
  • apps/frontend-manage/src/components/liveQuiz/cockpit/LiveQuizTimeline.tsx (1 hunks)
  • apps/frontend-pwa/src/pages/index.tsx (2 hunks)
  • apps/frontend-pwa/src/pages/session/[id].tsx (5 hunks)
  • packages/graphql/src/services/liveQuizzes.ts (1 hunks)
  • packages/i18n/messages/de.ts (2 hunks)
  • packages/i18n/messages/en.ts (2 hunks)
  • packages/prisma/src/prisma/schema/migrations/20250914194956_eduid_login_scope/migration.sql (1 hunks)
  • packages/prisma/src/prisma/schema/user.prisma (1 hunks)
  • turbo.json (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sjschlapbach sjschlapbach marked this pull request as ready for review September 14, 2025 20:59
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Sep 14, 2025
@sjschlapbach sjschlapbach merged commit baa104a into v3-assessment Sep 14, 2025
16 of 17 checks passed
@sjschlapbach sjschlapbach deleted the unauthorized-assessment-redirects branch September 14, 2025 21:00
@dosubot dosubot Bot added the enhancement label Sep 14, 2025
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
4.4% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement size:L This PR changes 100-499 lines, ignoring generated files.

Development

Successfully merging this pull request may close these issues.

1 participant