From 0092233a896b5905a0f2b5eb1293d6d03caf74b1 Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 20 Feb 2025 08:30:23 +0100 Subject: [PATCH 1/4] add access logging for failed authorization attempts --- .../domain/AuthenticationMechanism.java | 8 ++ .../localvc/LocalVCServletService.java | 87 ++++++++++++++++--- .../SshGitLocationResolverService.java | 3 + 3 files changed, 88 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java b/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java index 4f00e1bb117f..935fd86ff4aa 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java @@ -25,4 +25,12 @@ public enum AuthenticationMechanism { * The user attempted to authenticate to the LocalVC using either a user token or a participation token */ VCS_ACCESS_TOKEN, + /** + * The user used HTTPS + */ + HTTPS, + /** + * It is unclear what the user used + */ + OTHER } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java index e81d805d31c8..47f6acfe5d84 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; @@ -49,6 +50,7 @@ import de.tum.cit.aet.artemis.core.security.SecurityUtils; import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService; import de.tum.cit.aet.artemis.core.util.TimeLogUtil; +import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.domain.participation.Participation; import de.tum.cit.aet.artemis.programming.domain.AuthenticationMechanism; import de.tum.cit.aet.artemis.programming.domain.Commit; @@ -255,8 +257,15 @@ public void authenticateAndAuthorizeGitRequest(HttpServletRequest request, Repos throw new LocalVCForbiddenException(); } - var optionalParticipation = authorizeUser(repositoryTypeOrUserName, user, exercise, repositoryAction, localVCRepositoryUri, false); - savePreliminaryVcsAccessLogForHTTPs(request, localVCRepositoryUri, user, repositoryAction, optionalParticipation); + try { + var optionalParticipation = authorizeUser(repositoryTypeOrUserName, user, exercise, repositoryAction, localVCRepositoryUri, false); + savePreliminaryVcsAccessLogForHTTPs(request, localVCRepositoryUri, user, repositoryAction, optionalParticipation); + } + catch (LocalVCForbiddenException e) { + log.error("User {} does not have access to the repository {}", user.getLogin(), localVCRepositoryUri); + saveFailedAccessVcsAccessLog(Optional.of(request), Optional.empty(), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, repositoryAction); + throw new AccessDeniedException("User does not have access to this repository", e); + } log.debug("Authorizing user {} for repository {} took {}", user.getLogin(), localVCRepositoryUri, TimeLogUtil.formatDurationFrom(timeNanoStart)); } @@ -278,18 +287,66 @@ private void savePreliminaryVcsAccessLogForHTTPs(HttpServletRequest request, Loc var ipAddress = request.getRemoteAddr(); var authenticationMechanism = resolveHTTPSAuthenticationMechanism(request.getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); - String commitHash = null; + String finalCommitHash = getCommitHash(localVCRepositoryUri); + RepositoryActionType finalRepositoryAction = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH : RepositoryActionType.PULL; + vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, finalRepositoryAction, authenticationMechanism, finalCommitHash, ipAddress)); + } + } + + /** + * Logs a failed attempt to access a repository. + * + * @param request An optional {@link HttpServletRequest} containing request details if access was attempted via HTTPS. + * @param session An optional {@link ServerSession} containing session details if access was attempted via SSH. + * @param repositoryTypeOrUserName A string representing either the repository type or the username associated with the repository. + * @param exercise The {@link Exercise} associated with the repository. + * @param localVCRepositoryUri The {@link LocalVCRepositoryUri} representing the repository location. + * @param user The {@link User} attempting the access. + * @param repositoryAction The {@link RepositoryActionType} action that was attempted. + */ + public void saveFailedAccessVcsAccessLog(Optional request, Optional session, String repositoryTypeOrUserName, Exercise exercise, + LocalVCRepositoryUri localVCRepositoryUri, User user, RepositoryActionType repositoryAction) { + String ipAddress = ""; + AuthenticationMechanism authenticationMechanism = AuthenticationMechanism.OTHER; + var participation = tryToLoadParticipation(false, repositoryTypeOrUserName, localVCRepositoryUri, (ProgrammingExercise) exercise); + + // HTTPS + if (request.isPresent()) { + ipAddress = request.get().getRemoteAddr(); try { - commitHash = getLatestCommitHash(repositories.get(localVCRepositoryUri.getRelativeRepositoryPath().toString())); + authenticationMechanism = resolveHTTPSAuthenticationMechanism(request.get().getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); } - catch (GitAPIException e) { - log.warn("Failed to obtain commit hash for repository {}. Error: {}", localVCRepositoryUri.getRelativeRepositoryPath().toString(), e.getMessage()); + catch (LocalVCAuthException ignored) { + authenticationMechanism = AuthenticationMechanism.HTTPS; } + } + // SSH + if (session.isPresent()) { + ipAddress = session.get().getClientAddress().toString(); + authenticationMechanism = AuthenticationMechanism.SSH; + } - String finalCommitHash = commitHash; - RepositoryActionType finalRepositoryAction = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH : RepositoryActionType.PULL; - vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, finalRepositoryAction, authenticationMechanism, finalCommitHash, ipAddress)); + String finalCommitHash = getCommitHash(localVCRepositoryUri); + var finalAuthenticationMechanism = authenticationMechanism; + var finalIpAddress = ipAddress; + RepositoryActionType finalRepositoryAction = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH_FAIL : RepositoryActionType.CLONE_FAIL; + vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, finalRepositoryAction, finalAuthenticationMechanism, finalCommitHash, finalIpAddress)); + } + + /** + * Retrieves the latest commit hash from the given repository. + * + * @param localVCRepositoryUri The {@link LocalVCRepositoryUri} representing the repository location. + * @return The latest commit hash as a string, or an empty string if retrieval fails. + */ + private String getCommitHash(LocalVCRepositoryUri localVCRepositoryUri) { + try { + return getLatestCommitHash(repositories.get(localVCRepositoryUri.getRelativeRepositoryPath().toString())); + } + catch (GitAPIException e) { + log.warn("Failed to obtain commit hash for repository {}. Error: {}", localVCRepositoryUri.getRelativeRepositoryPath().toString(), e.getMessage()); } + return ""; } /** @@ -482,7 +539,7 @@ private UsernameAndPassword extractUsernameAndPassword(String authorizationHeade * @param repositoryActionType The type of the action the user wants to perform. * @param localVCRepositoryUri The URI of the local repository. * @param usingSSH The flag specifying whether the method is called from the SSH or HTTPs context - * @return the ProgrammingParticipation Optional, containing the participation fetched during authorization + * @return the ProgrammingParticipation Optional, containing the fetched participation * @throws LocalVCForbiddenException If the user is not allowed to access the repository. */ public Optional authorizeUser(String repositoryTypeOrUserName, User user, ProgrammingExercise exercise, @@ -499,6 +556,16 @@ public Optional authorizeUser(String repositor return Optional.of(participation); } + /** + * Attempts to load a programming exercise participation based on the provided parameters. + * + * @param usingSSH {@code true} if the user's session is over SSH, {@code false} if over HTTP + * @param repositoryTypeOrUserName A string representing either the repository type or the username associated with the repository. + * @param localVCRepositoryUri The local version control repository URI. + * @param exercise The programming exercise for which participation is being fetched. + * @return The fetched {@link ProgrammingExerciseParticipation} instance. + * @throws LocalVCInternalException If no participation is found and it is not an auxiliary repository. + */ private ProgrammingExerciseParticipation tryToLoadParticipation(boolean usingSSH, String repositoryTypeOrUserName, LocalVCRepositoryUri localVCRepositoryUri, ProgrammingExercise exercise) throws LocalVCInternalException { ProgrammingExerciseParticipation participation; diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java index 94f8ae6f7ec6..57832eaa6f17 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java @@ -6,6 +6,7 @@ import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.Path; +import java.util.Optional; import org.apache.sshd.git.GitLocationResolver; import org.apache.sshd.server.session.ServerSession; @@ -83,6 +84,8 @@ public Path resolveRootDirectory(String command, String[] args, ServerSession se } catch (LocalVCForbiddenException e) { log.error("User {} does not have access to the repository {}", user.getLogin(), repositoryPath); + localVCServletService.saveFailedAccessVcsAccessLog(Optional.empty(), Optional.of(session), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, + repositoryAction); throw new AccessDeniedException("User does not have access to this repository", e); } } From 89c9b9247ba02d901776bd98cae8f99055493417 Mon Sep 17 00:00:00 2001 From: entholzer Date: Sun, 23 Feb 2025 09:54:46 +0100 Subject: [PATCH 2/4] make method more compact --- .../localvc/LocalVCServletService.java | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java index 47f6acfe5d84..42d8d6b9e146 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java @@ -306,31 +306,48 @@ private void savePreliminaryVcsAccessLogForHTTPs(HttpServletRequest request, Loc */ public void saveFailedAccessVcsAccessLog(Optional request, Optional session, String repositoryTypeOrUserName, Exercise exercise, LocalVCRepositoryUri localVCRepositoryUri, User user, RepositoryActionType repositoryAction) { - String ipAddress = ""; - AuthenticationMechanism authenticationMechanism = AuthenticationMechanism.OTHER; var participation = tryToLoadParticipation(false, repositoryTypeOrUserName, localVCRepositoryUri, (ProgrammingExercise) exercise); + var commitHash = getCommitHash(localVCRepositoryUri); + var authenticationMechanism = resolveAuthenticationMechanismFromSessionOrRequest(request, session, user); + var action = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH_FAIL : RepositoryActionType.CLONE_FAIL; + var ipAddress = request.isPresent() ? request.get().getRemoteAddr() : (session.isPresent() ? session.get().getClientAddress().toString() : ""); + vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, action, authenticationMechanism, commitHash, ipAddress)); + } - // HTTPS - if (request.isPresent()) { - ipAddress = request.get().getRemoteAddr(); + /** + * Determines the authentication mechanism based on the provided session or request. + * + *

+ * If a {@link ServerSession} is present, the authentication mechanism is assumed to be SSH. + *

+ *

+ * If an {@link HttpServletRequest} is present, the method attempts to resolve the authentication + * mechanism using the authorization header. If an exception occurs, HTTPS authentication is assumed by default. + *

+ *

+ * If neither a session nor a request is available, the authentication mechanism defaults to OTHER. + *

+ * + * @param request an {@link Optional} containing the HTTP request, if available + * @param session an {@link Optional} containing the server session, if available + * @param user the user for whom authentication is being determined + * @return the resolved {@link AuthenticationMechanism} + */ + private AuthenticationMechanism resolveAuthenticationMechanismFromSessionOrRequest(Optional request, Optional session, User user) { + if (session.isPresent()) { + return AuthenticationMechanism.SSH; + } + else if (request.isPresent()) { try { - authenticationMechanism = resolveHTTPSAuthenticationMechanism(request.get().getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); + return resolveHTTPSAuthenticationMechanism(request.get().getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); } catch (LocalVCAuthException ignored) { - authenticationMechanism = AuthenticationMechanism.HTTPS; + return AuthenticationMechanism.HTTPS; } } - // SSH - if (session.isPresent()) { - ipAddress = session.get().getClientAddress().toString(); - authenticationMechanism = AuthenticationMechanism.SSH; + else { + return AuthenticationMechanism.OTHER; } - - String finalCommitHash = getCommitHash(localVCRepositoryUri); - var finalAuthenticationMechanism = authenticationMechanism; - var finalIpAddress = ipAddress; - RepositoryActionType finalRepositoryAction = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH_FAIL : RepositoryActionType.CLONE_FAIL; - vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, finalRepositoryAction, finalAuthenticationMechanism, finalCommitHash, finalIpAddress)); } /** From 121de51a4d039c4e82fbd3dd9525a0fca293ee64 Mon Sep 17 00:00:00 2001 From: entholzer Date: Tue, 25 Feb 2025 11:35:09 +0100 Subject: [PATCH 3/4] throw error again after interception --- .../programming/service/localvc/LocalVCServletService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java index 42d8d6b9e146..9c7928b29688 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java @@ -32,7 +32,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.http.HttpStatus; -import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; @@ -264,7 +263,7 @@ public void authenticateAndAuthorizeGitRequest(HttpServletRequest request, Repos catch (LocalVCForbiddenException e) { log.error("User {} does not have access to the repository {}", user.getLogin(), localVCRepositoryUri); saveFailedAccessVcsAccessLog(Optional.of(request), Optional.empty(), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, repositoryAction); - throw new AccessDeniedException("User does not have access to this repository", e); + throw e; } log.debug("Authorizing user {} for repository {} took {}", user.getLogin(), localVCRepositoryUri, TimeLogUtil.formatDurationFrom(timeNanoStart)); From f659e9819021352b909bcfe11e60a24fd01b9ce1 Mon Sep 17 00:00:00 2001 From: entholzer Date: Tue, 25 Feb 2025 15:02:15 +0100 Subject: [PATCH 4/4] sumtype pattern --- .../domain/AuthenticationMechanism.java | 8 +--- .../localvc/AuthenticationContext.java | 26 +++++++++++++ .../localvc/LocalVCServletService.java | 39 +++++++++---------- .../SshGitLocationResolverService.java | 3 +- 4 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/AuthenticationContext.java diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java b/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java index 935fd86ff4aa..7e5ffd7e7172 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/domain/AuthenticationMechanism.java @@ -26,11 +26,7 @@ public enum AuthenticationMechanism { */ VCS_ACCESS_TOKEN, /** - * The user used HTTPS + * The authentication header was missing */ - HTTPS, - /** - * It is unclear what the user used - */ - OTHER + NONE } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/AuthenticationContext.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/AuthenticationContext.java new file mode 100644 index 000000000000..129906e771cc --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/AuthenticationContext.java @@ -0,0 +1,26 @@ +package de.tum.cit.aet.artemis.programming.service.localvc; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.sshd.server.session.ServerSession; + +public sealed interface AuthenticationContext { + + record Session(ServerSession session) implements AuthenticationContext { + + @Override + public String getIpAddress() { + return session.getClientAddress().toString(); + } + } + + record Request(HttpServletRequest request) implements AuthenticationContext { + + @Override + public String getIpAddress() { + return request.getRemoteAddr(); + } + } + + String getIpAddress(); +} diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java index 9c7928b29688..3466a78ea35c 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/LocalVCServletService.java @@ -262,7 +262,7 @@ public void authenticateAndAuthorizeGitRequest(HttpServletRequest request, Repos } catch (LocalVCForbiddenException e) { log.error("User {} does not have access to the repository {}", user.getLogin(), localVCRepositoryUri); - saveFailedAccessVcsAccessLog(Optional.of(request), Optional.empty(), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, repositoryAction); + saveFailedAccessVcsAccessLog(new AuthenticationContext.Request(request), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, repositoryAction); throw e; } @@ -295,21 +295,20 @@ private void savePreliminaryVcsAccessLogForHTTPs(HttpServletRequest request, Loc /** * Logs a failed attempt to access a repository. * - * @param request An optional {@link HttpServletRequest} containing request details if access was attempted via HTTPS. - * @param session An optional {@link ServerSession} containing session details if access was attempted via SSH. + * @param context the Authentication context * @param repositoryTypeOrUserName A string representing either the repository type or the username associated with the repository. * @param exercise The {@link Exercise} associated with the repository. * @param localVCRepositoryUri The {@link LocalVCRepositoryUri} representing the repository location. * @param user The {@link User} attempting the access. * @param repositoryAction The {@link RepositoryActionType} action that was attempted. */ - public void saveFailedAccessVcsAccessLog(Optional request, Optional session, String repositoryTypeOrUserName, Exercise exercise, - LocalVCRepositoryUri localVCRepositoryUri, User user, RepositoryActionType repositoryAction) { + public void saveFailedAccessVcsAccessLog(AuthenticationContext context, String repositoryTypeOrUserName, Exercise exercise, LocalVCRepositoryUri localVCRepositoryUri, + User user, RepositoryActionType repositoryAction) { var participation = tryToLoadParticipation(false, repositoryTypeOrUserName, localVCRepositoryUri, (ProgrammingExercise) exercise); var commitHash = getCommitHash(localVCRepositoryUri); - var authenticationMechanism = resolveAuthenticationMechanismFromSessionOrRequest(request, session, user); + var authenticationMechanism = resolveAuthenticationMechanismFromSessionOrRequest(context, user); var action = repositoryAction == RepositoryActionType.WRITE ? RepositoryActionType.PUSH_FAIL : RepositoryActionType.CLONE_FAIL; - var ipAddress = request.isPresent() ? request.get().getRemoteAddr() : (session.isPresent() ? session.get().getClientAddress().toString() : ""); + var ipAddress = context.getIpAddress(); vcsAccessLogService.ifPresent(service -> service.saveAccessLog(user, participation, action, authenticationMechanism, commitHash, ipAddress)); } @@ -327,26 +326,24 @@ public void saveFailedAccessVcsAccessLog(Optional request, O * If neither a session nor a request is available, the authentication mechanism defaults to OTHER. *

* - * @param request an {@link Optional} containing the HTTP request, if available - * @param session an {@link Optional} containing the server session, if available + * @param context the Authentication context * @param user the user for whom authentication is being determined * @return the resolved {@link AuthenticationMechanism} */ - private AuthenticationMechanism resolveAuthenticationMechanismFromSessionOrRequest(Optional request, Optional session, User user) { - if (session.isPresent()) { - return AuthenticationMechanism.SSH; - } - else if (request.isPresent()) { - try { - return resolveHTTPSAuthenticationMechanism(request.get().getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); + private AuthenticationMechanism resolveAuthenticationMechanismFromSessionOrRequest(AuthenticationContext context, User user) { + switch (context) { + case AuthenticationContext.Session ignored -> { + return AuthenticationMechanism.SSH; } - catch (LocalVCAuthException ignored) { - return AuthenticationMechanism.HTTPS; + case AuthenticationContext.Request request -> { + try { + return resolveHTTPSAuthenticationMechanism(request.request().getHeader(LocalVCServletService.AUTHORIZATION_HEADER), user); + } + catch (LocalVCAuthException ignored) { + return AuthenticationMechanism.NONE; + } } } - else { - return AuthenticationMechanism.OTHER; - } } /** diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java index 57832eaa6f17..6f2875c0fd94 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/SshGitLocationResolverService.java @@ -6,7 +6,6 @@ import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.Path; -import java.util.Optional; import org.apache.sshd.git.GitLocationResolver; import org.apache.sshd.server.session.ServerSession; @@ -84,7 +83,7 @@ public Path resolveRootDirectory(String command, String[] args, ServerSession se } catch (LocalVCForbiddenException e) { log.error("User {} does not have access to the repository {}", user.getLogin(), repositoryPath); - localVCServletService.saveFailedAccessVcsAccessLog(Optional.empty(), Optional.of(session), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, + localVCServletService.saveFailedAccessVcsAccessLog(new AuthenticationContext.Session(session), repositoryTypeOrUserName, exercise, localVCRepositoryUri, user, repositoryAction); throw new AccessDeniedException("User does not have access to this repository", e); }