From 9e9d63a229072c29463ff760f76ad095a8a9a9c4 Mon Sep 17 00:00:00 2001 From: entholzer Date: Mon, 11 Nov 2024 13:07:19 +0100 Subject: [PATCH] fix access token not showing up in repository view --- .../core/service/user/UserService.java | 2 +- .../aet/artemis/core/web/AccountResource.java | 2 +- .../ParticipationVcsAccessTokenService.java | 24 ++++++++++++++----- .../repository-view.component.html | 2 ++ .../code-button/code-button.component.html | 4 ++-- .../code-button/code-button.component.ts | 13 +++++++--- .../icl/LocalVCIntegrationTest.java | 2 +- .../icl/LocalVCLocalCITestService.java | 6 ++--- 8 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java b/src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java index c883f774dcad..d06ecfec87af 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java @@ -832,7 +832,7 @@ public List importUsers(List userDtos) { * @return the users participation vcs access token, or throws an exception if it does not exist */ public ParticipationVCSAccessToken getParticipationVcsAccessTokenForUserAndParticipationIdOrElseThrow(User user, Long participationId) { - return participationVCSAccessTokenService.findByUserIdAndParticipationIdOrElseThrow(user.getId(), participationId); + return participationVCSAccessTokenService.findByUserAndParticipationIdOrElseThrow(user, participationId); } /** diff --git a/src/main/java/de/tum/cit/aet/artemis/core/web/AccountResource.java b/src/main/java/de/tum/cit/aet/artemis/core/web/AccountResource.java index 2a441e4cd035..70fc3c57bd80 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/web/AccountResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/web/AccountResource.java @@ -233,7 +233,7 @@ public ResponseEntity getVcsAccessToken(@RequestParam("participationId") } /** - * PUT account/participation-vcs-access-token : get the vcsToken for of a user for a participation + * PUT account/participation-vcs-access-token : add a vcsToken for of a user for a participation * * @param participationId the participation for which the access token should be fetched * diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java index 7c41d9f8452d..db9cebb2eb6c 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Service; import de.tum.cit.aet.artemis.core.domain.User; +import de.tum.cit.aet.artemis.core.exception.AccessForbiddenException; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.programming.domain.ParticipationVCSAccessToken; import de.tum.cit.aet.artemis.programming.repository.ParticipationVCSAccessTokenRepository; @@ -46,18 +47,24 @@ public ParticipationVCSAccessToken createParticipationVCSAccessToken(User user, } /** - * Retrieves the participationVCSAccessToken for a User,Participation pair if it exists + * Retrieves the participationVCSAccessToken for a User,Participation pair if it exists and if the user owns the participation * - * @param userId the user's id which is owner of the token + * @param user the user which is owner of the token * @param participationId the participation's id which the token belongs to * @return an Optional participationVCSAccessToken, */ - public ParticipationVCSAccessToken findByUserIdAndParticipationIdOrElseThrow(long userId, long participationId) { - return participationVcsAccessTokenRepository.findByUserIdAndParticipationIdOrElseThrow(userId, participationId); + public ParticipationVCSAccessToken findByUserAndParticipationIdOrElseThrow(User user, long participationId) { + var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId); + if (participation.isOwnedBy(user)) { + return participationVcsAccessTokenRepository.findByUserIdAndParticipationIdOrElseThrow(user.getId(), participationId); + } + else { + throw new AccessForbiddenException("Participation not owned by user"); + } } /** - * Checks if the participationVCSAccessToken for a User,Participation pair exists, and creates a new one if not + * Checks if the participationVCSAccessToken for a User,Participation pair exists, and creates a new one if not; if the user owns the participation * * @param user the user's id which is owner of the token * @param participationId the participation's id which the token belongs to @@ -66,7 +73,12 @@ public ParticipationVCSAccessToken findByUserIdAndParticipationIdOrElseThrow(lon public ParticipationVCSAccessToken createVcsAccessTokenForUserAndParticipationIdOrElseThrow(User user, long participationId) { participationVcsAccessTokenRepository.findByUserIdAndParticipationIdAndThrowIfExists(user.getId(), participationId); var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId); - return createParticipationVCSAccessToken(user, participation); + if (participation.isOwnedBy(user)) { + return createParticipationVCSAccessToken(user, participation); + } + else { + throw new AccessForbiddenException("Participation not owned by user"); + } } /** diff --git a/src/main/webapp/app/localvc/repository-view/repository-view.component.html b/src/main/webapp/app/localvc/repository-view/repository-view.component.html index 6a41335a4f51..24c332323ed4 100644 --- a/src/main/webapp/app/localvc/repository-view/repository-view.component.html +++ b/src/main/webapp/app/localvc/repository-view/repository-view.component.html @@ -47,6 +47,8 @@

[smallButtons]="false" [routerLinkForRepositoryView]="'.'" [repositoryUri]="repositoryUri" + [participations]="[participation]" + [useParticipationVcsAccessToken]="true" [exercise]="exercise" /> } diff --git a/src/main/webapp/app/shared/components/code-button/code-button.component.html b/src/main/webapp/app/shared/components/code-button/code-button.component.html index 9b8d4f0488fd..80972a802a38 100644 --- a/src/main/webapp/app/shared/components/code-button/code-button.component.html +++ b/src/main/webapp/app/shared/components/code-button/code-button.component.html @@ -17,10 +17,10 @@ @if (useSsh && !copyEnabled) {
} - @if (useToken && !copyEnabled && tokenMissing) { + @if (useToken && tokenMissing) {
} - @if (useToken && !copyEnabled && tokenExpired) { + @if (useToken && tokenExpired) {
} @if (participations && participations.length > 1) { diff --git a/src/main/webapp/app/shared/components/code-button/code-button.component.ts b/src/main/webapp/app/shared/components/code-button/code-button.component.ts index 8f83edec0be8..7e4e0d33e766 100644 --- a/src/main/webapp/app/shared/components/code-button/code-button.component.ts +++ b/src/main/webapp/app/shared/components/code-button/code-button.component.ts @@ -92,7 +92,6 @@ export class CodeButtonComponent implements OnInit, OnChanges { this.copyEnabled = true; this.useSsh = this.localStorage.retrieve('useSsh') || false; this.useToken = this.localStorage.retrieve('useToken') || false; - this.loadParticipationVcsAccessTokens(); // Get ssh information from the user this.profileService.getProfileInfo().subscribe((profileInfo) => { @@ -124,6 +123,7 @@ export class CodeButtonComponent implements OnInit, OnChanges { if (this.useToken) { this.useHttpsUrlWithToken(); } + this.loadParticipationVcsAccessTokens(); }); this.ideSettingsService.loadIdePreferences().then((programmingLanguageToIde) => { @@ -159,7 +159,7 @@ export class CodeButtonComponent implements OnInit, OnChanges { public useHttpsUrlWithToken() { this.useSsh = false; this.useToken = true; - this.copyEnabled = !!(this.accessTokensEnabled && this.useToken && ((!!this.user.vcsAccessToken && !this.isTokenExpired()) || this.useParticipationVcsAccessToken)); + this.copyEnabled = !!(this.accessTokensEnabled && ((!!this.user.vcsAccessToken && !this.isTokenExpired()) || this.useParticipationVcsAccessToken)); this.refreshTokenState(); this.storeToLocalStorage(); } @@ -233,6 +233,9 @@ export class CodeButtonComponent implements OnInit, OnChanges { if (error.status == 404) { this.createNewVcsAccessToken(participation); } + if (error.status == 403) { + this.useParticipationVcsAccessToken = false; + } }, }); } @@ -250,7 +253,11 @@ export class CodeButtonComponent implements OnInit, OnChanges { } } }, - error: () => {}, + error: (error: HttpErrorResponse) => { + if (error.status == 403) { + this.useParticipationVcsAccessToken = false; + } + }, }); } diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java index af998a54a556..4f6840fd63f4 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java @@ -110,7 +110,7 @@ void testFetchPush_repositoryDoesNotExist() throws IOException, GitAPIException, void testFetchPush_usingVcsAccessToken() { var programmingParticipation = localVCLocalCITestService.createParticipation(programmingExercise, student1Login); var student = userUtilService.getUserByLogin(student1Login); - var participationVcsAccessToken = localVCLocalCITestService.getParticipationVcsAccessToken(student.getId(), programmingParticipation.getId()); + var participationVcsAccessToken = localVCLocalCITestService.getParticipationVcsAccessToken(student, programmingParticipation.getId()); var token = participationVcsAccessToken.getVcsAccessToken(); programmingExerciseRepository.save(programmingExercise); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java index c6d7556e3766..7ad94838921f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java @@ -676,13 +676,13 @@ public void verifyRepositoryFoldersExist(ProgrammingExercise programmingExercise /** * Gets the participationVcsAccessToken belonging to a user and a participation * - * @param userId The user's id + * @param user The user * @param programmingParticipationId The participation's id * * @return the participationVcsAccessToken of the user for the given participationId */ - public ParticipationVCSAccessToken getParticipationVcsAccessToken(Long userId, Long programmingParticipationId) { - return participationVcsAccessTokenService.findByUserIdAndParticipationIdOrElseThrow(userId, programmingParticipationId); + public ParticipationVCSAccessToken getParticipationVcsAccessToken(User user, Long programmingParticipationId) { + return participationVcsAccessTokenService.findByUserAndParticipationIdOrElseThrow(user, programmingParticipationId); } /**