diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationService.java b/src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationService.java index c2a1761b6b46..1a981ee84f99 100644 --- a/src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationService.java +++ b/src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationService.java @@ -143,7 +143,9 @@ public Optional isMemberOrCreateForCourseWideElseThrow(Long conver if (conversation instanceof Channel channel && channel.getIsCourseWide()) { ConversationParticipant conversationParticipant = ConversationParticipant.createWithDefaultValues(user, channel); - conversationParticipant.setIsModerator(authorizationCheckService.isAtLeastInstructorInCourse(channel.getCourse(), user)); + boolean canBecomeModerator = (channel.getIsAnnouncementChannel() ? authorizationCheckService.isAtLeastInstructorInCourse(channel.getCourse(), user) + : authorizationCheckService.isAtLeastTeachingAssistantInCourse(channel.getCourse(), user)); + conversationParticipant.setIsModerator(canBecomeModerator); lastReadDate.ifPresent(conversationParticipant::setLastRead); conversationParticipantRepository.saveAndFlush(conversationParticipant); } diff --git a/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts b/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts index eed3ef65d59e..8a843639365a 100644 --- a/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts +++ b/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts @@ -74,10 +74,10 @@ export class AnswerPostReactionsBarComponent extends PostingsReactionsBarDirecti this.isAuthorOfOriginalPost = this.metisService.metisUserIsAuthorOfPosting(this.posting.post!); this.isAnswerOfAnnouncement = getAsChannelDTO(this.posting.post?.conversation)?.isAnnouncementChannel ?? false; const isCourseWideChannel = getAsChannelDTO(this.posting.post?.conversation)?.isCourseWide ?? false; - const isAtLeastInstructorInCourse = this.metisService.metisUserIsAtLeastInstructorInCourse(); - const mayEditOrDeleteOtherUsersAnswer = - (isCourseWideChannel && isAtLeastInstructorInCourse) || (getAsChannelDTO(this.metisService.getCurrentConversation())?.hasChannelModerationRights ?? false); - this.mayDelete = !this.isReadOnlyMode && (this.isAuthorOfPosting || mayEditOrDeleteOtherUsersAnswer); + const canDeletePost = this.isAnswerOfAnnouncement ? this.metisService.metisUserIsAtLeastInstructorInCourse() : this.metisService.metisUserIsAtLeastTutorInCourse(); + const mayDeleteOtherUsersAnswer = + (isCourseWideChannel && canDeletePost) || (getAsChannelDTO(this.metisService.getCurrentConversation())?.hasChannelModerationRights ?? false); + this.mayDelete = !this.isReadOnlyMode && (this.isAuthorOfPosting || (mayDeleteOtherUsersAnswer && canDeletePost)); this.mayDeleteOutput.emit(this.mayDelete); } diff --git a/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts b/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts index 569eec43b75f..9213fcaeae56 100644 --- a/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts +++ b/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts @@ -100,7 +100,7 @@ export class PostReactionsBarComponent extends PostingsReactionsBarDirective { it('should display the delete option to instructor if posting is in course-wide channel from a student', () => { metisServiceUserIsAtLeastInstructorMock.mockReturnValue(true); metisServiceUserPostingAuthorMock.mockReturnValue(false); + metisServiceUserIsAtLeastTutorMock.mockReturnValue(true); component.posting = { ...metisResolvingAnswerPostUser1, post: { ...metisPostInChannel } }; component.posting.authorRole = UserRole.USER; component.ngOnInit(); @@ -158,7 +159,7 @@ describe('AnswerPostReactionsBarComponent', () => { expect(getEditButton()).not.toBeNull(); }); - it('should not display edit and delete options to tutor if posting is in course-wide channel from a student', () => { + it('should display edit and delete options to tutor if posting is in course-wide channel from a student', () => { metisServiceUserIsAtLeastInstructorMock.mockReturnValue(false); metisServiceUserIsAtLeastTutorMock.mockReturnValue(true); metisServiceUserPostingAuthorMock.mockReturnValue(false); @@ -167,7 +168,7 @@ describe('AnswerPostReactionsBarComponent', () => { component.ngOnInit(); fixture.detectChanges(); expect(getEditButton()).toBeNull(); - expect(getDeleteButton()).toBeNull(); + expect(getDeleteButton()).not.toBeNull(); }); it('should not display edit and delete options to users that are neither author or tutor', () => { diff --git a/src/test/javascript/spec/component/shared/metis/postings-reactions-bar/post-reactions-bar/post-reactions-bar.component.spec.ts b/src/test/javascript/spec/component/shared/metis/postings-reactions-bar/post-reactions-bar/post-reactions-bar.component.spec.ts index ce01de09f53b..c567c465fe56 100644 --- a/src/test/javascript/spec/component/shared/metis/postings-reactions-bar/post-reactions-bar/post-reactions-bar.component.spec.ts +++ b/src/test/javascript/spec/component/shared/metis/postings-reactions-bar/post-reactions-bar/post-reactions-bar.component.spec.ts @@ -223,7 +223,7 @@ describe('PostReactionsBarComponent', () => { expect(debugElement.query(By.directive(ConfirmIconComponent))).toBeNull(); }); - it('should not display edit and delete options to tutor if posting is in course-wide channel', () => { + it('should not display edit option but should display delete option to tutor if posting is in course-wide channel', () => { metisServiceUserIsAtLeastInstructorStub.mockReturnValue(false); metisServiceUserIsAtLeastTutorStub.mockReturnValue(true); metisServiceUserIsAuthorOfPostingStub.mockReturnValue(false); @@ -232,7 +232,7 @@ describe('PostReactionsBarComponent', () => { component.ngOnInit(); fixture.detectChanges(); expect(getEditButton()).toBeNull(); - expect(getDeleteButton()).toBeNull(); + expect(getDeleteButton()).not.toBeNull(); }); it('should not display edit and delete options to tutor if posting is announcement', () => { @@ -257,11 +257,14 @@ describe('PostReactionsBarComponent', () => { it('should display the delete option to instructor if posting is in course-wide channel from a student', () => { metisServiceUserIsAtLeastInstructorStub.mockReturnValue(true); + metisServiceUserIsAtLeastTutorStub.mockReturnValue(true); metisServiceUserIsAuthorOfPostingStub.mockReturnValue(false); component.posting = { ...metisPostInChannel }; component.posting.authorRole = UserRole.USER; + component.ngOnInit(); fixture.detectChanges(); + component.setMayDelete(); expect(getDeleteButton()).not.toBeNull(); });