From 970e6b09cc96f9e16cd66b439bbc80b94fc50d5e Mon Sep 17 00:00:00 2001 From: Betsy Castro <5490820+betsyecastro@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:25:54 -0500 Subject: [PATCH 1/2] Adds viewForAssociatedProfile() policy to StudentPolicy --- app/Policies/StudentPolicy.php | 14 +++++++- app/Student.php | 10 ++++++ tests/Feature/ProfileStudentTest.php | 50 ++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/app/Policies/StudentPolicy.php b/app/Policies/StudentPolicy.php index e2fb8529..dcc4ff12 100644 --- a/app/Policies/StudentPolicy.php +++ b/app/Policies/StudentPolicy.php @@ -2,6 +2,7 @@ namespace App\Policies; +use App\Profile; use App\Student; use App\User; use Illuminate\Auth\Access\HandlesAuthorization; @@ -35,6 +36,17 @@ public function viewAny(User $user) return $user->userOrDelegatorhasRole(['faculty', 'students_admin']); } + /** + * Determine whether the student can be viewed by the associated profile's user. + * + * @param \App\User $user + * @return \Illuminate\Auth\Access\Response|bool + */ + public function viewForAssociatedProfile(User $user, Student $student) + { + return $student->isAssociatedToUserProfiles($user); + } + /** * Determine whether the user can view the student. * @@ -44,7 +56,7 @@ public function viewAny(User $user) */ public function view(User $user, Student $student) { - return $this->viewAny($user) || $user->owns($student, true); + return $this->viewAny($user) || $user->owns($student, true) || $this->viewForAssociatedProfile($user, $student); } /** diff --git a/app/Student.php b/app/Student.php index fbecf415..cfb8c37e 100644 --- a/app/Student.php +++ b/app/Student.php @@ -188,6 +188,16 @@ public function tagTypes(): array ->all(); } + /** + * Determine whether the profile(s) of a given user is associated to the student. + */ + public function isAssociatedToUserProfiles(User $user) + { + $profile_ids = $user->profiles()->pluck('id'); + + return $this->faculty()->whereKey($profile_ids)->exists(); + } + //////////////////////////////////// // Mutators and Virtual Attributes// //////////////////////////////////// diff --git a/tests/Feature/ProfileStudentTest.php b/tests/Feature/ProfileStudentTest.php index 24940967..14bcc9e4 100644 --- a/tests/Feature/ProfileStudentTest.php +++ b/tests/Feature/ProfileStudentTest.php @@ -64,4 +64,54 @@ public function testProfileStudentView(): void ->assertViewIs('students.profile-students') ->assertSee($student->full_name); } + + /** + * Test Profile (non-faculty) specific view of students + * + * @return void + */ + public function testNonFcultyProfileStudentView(): void + { + $associated_profile = Profile::factory() + ->hasData() + ->create(); + + $non_associated_profile= Profile::factory() + ->hasData() + ->create(); + + $student = Student::factory() + ->submitted() + ->has(StudentData::factory(), 'research_profile') + ->hasAttached($associated_profile, [], 'faculty') + ->create(); + + $profile_student_route = route('profiles.students', ['profile' => $non_associated_profile]); + $show_route = route('students.show', ['student' => $student]); + + $this->loginAsUserWithRole('staff', $non_associated_profile->user); + $this->get($show_route) + ->assertStatus(403); + + $this->loginAsUserWithRole('faculty', $non_associated_profile->user); + $this->get($profile_student_route) + ->assertStatus(200) + ->assertViewIs('students.profile-students') + ->assertDontSee($student->full_name); + + $this->get($show_route) + ->assertStatus(200); + + $profile_student_route = route('profiles.students', ['profile' => $associated_profile]); + + $this->loginAsUserWithRole('staff', $associated_profile->user); + $this->get($profile_student_route) + ->assertStatus(200) + ->assertViewIs('students.profile-students') + ->assertSee($student->full_name); + + $this->get($show_route) + ->assertStatus(200) + ->assertSee($student->full_name); + } } From db75ad2fdf9e20f3ddc4ee5365400bbd756187d5 Mon Sep 17 00:00:00 2001 From: Betsy Castro <5490820+betsyecastro@users.noreply.github.com> Date: Fri, 22 Aug 2025 10:26:52 -0500 Subject: [PATCH 2/2] Allows Non-faculty profile to add feedback to an associated student app --- app/Http/Livewire/StudentFeedback.php | 2 +- app/Policies/StudentFeedbackPolicy.php | 7 +++++-- resources/views/livewire/student-feedback.blade.php | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/Http/Livewire/StudentFeedback.php b/app/Http/Livewire/StudentFeedback.php index f98f9cbe..927bbe86 100644 --- a/app/Http/Livewire/StudentFeedback.php +++ b/app/Http/Livewire/StudentFeedback.php @@ -24,7 +24,7 @@ public function getFeedbackProperty() public function add() { - $this->authorize('create', StudentFeedbackEntry::class); + $this->authorize('create', [StudentFeedbackEntry::class, $this->student]); $feedback = $this->student->feedback()->create([ 'data' => $this->new_feedback + ['submitted_by' => auth()->user()->id ?? 'system'], diff --git a/app/Policies/StudentFeedbackPolicy.php b/app/Policies/StudentFeedbackPolicy.php index c4a335d9..75f032c7 100644 --- a/app/Policies/StudentFeedbackPolicy.php +++ b/app/Policies/StudentFeedbackPolicy.php @@ -2,6 +2,7 @@ namespace App\Policies; +use App\Student; use App\StudentFeedback; use App\User; use Illuminate\Auth\Access\HandlesAuthorization; @@ -55,9 +56,11 @@ public function view(User $user, StudentFeedback $studentFeedback) * @param \App\User $user * @return mixed */ - public function create(User $user) + public function create(User $user, Student $student) { - return $user->userOrDelegatorhasRole(['faculty', 'students_admin']); + $assoc_profile_can_add_feedback = $student->isAssociatedToUserProfiles($user); + + return $user->userOrDelegatorhasRole(['faculty', 'students_admin']) || $assoc_profile_can_add_feedback; } /** diff --git a/resources/views/livewire/student-feedback.blade.php b/resources/views/livewire/student-feedback.blade.php index fbacf620..5504c469 100644 --- a/resources/views/livewire/student-feedback.blade.php +++ b/resources/views/livewire/student-feedback.blade.php @@ -1,6 +1,6 @@
{{-- Feedback form --}} - @can('create', App\StudentFeedback::class) + @can('create', [App\StudentFeedback::class, $student])