diff --git a/pom.xml b/pom.xml
index f46bbb52ac9916060500d4fc6b670a084eb07a42..c3c1f52e5692ef89f25010dcd2f217b51ca0df33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -285,7 +285,7 @@
         <dependency>
 		    <groupId>org.gitlab4j</groupId>
 		    <artifactId>gitlab4j-api</artifactId>
-		    <version>5.0.1</version>
+		    <version>5.6.0</version>
 		</dependency>
         <dependency>
             <groupId>org.eclipse.jgit</groupId>
diff --git a/src/main/java/at/ac/uibk/gitsearch/config/CacheConfiguration.java b/src/main/java/at/ac/uibk/gitsearch/config/CacheConfiguration.java
index 433b24ae6a4a54c37a8718003d6010132669ae99..c1cd5357121532429746a760f32d644092304f07 100644
--- a/src/main/java/at/ac/uibk/gitsearch/config/CacheConfiguration.java
+++ b/src/main/java/at/ac/uibk/gitsearch/config/CacheConfiguration.java
@@ -1,5 +1,6 @@
 package at.ac.uibk.gitsearch.config;
 
+import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
 import at.ac.uibk.gitsearch.repository.search.MetaDataRepository;
 import at.ac.uibk.gitsearch.service.EditorialPagesService;
 import java.time.Duration;
@@ -50,6 +51,7 @@ public class CacheConfiguration {
     return cm -> {
       createCache(cm, at.ac.uibk.gitsearch.repository.jpa.UserRepository.USERS_BY_LOGIN_CACHE);
       createCache(cm, at.ac.uibk.gitsearch.repository.jpa.UserRepository.USERS_BY_EMAIL_CACHE);
+      createCache(cm, GitLabRepository.FULLPATH_OF_GROUP_CACHE);
       createCache(cm, EditorialPagesService.PAGES_CACHE);
       createCache(cm, EditorialPagesService.HELPMENUTREE_CACHE);
 
diff --git a/src/main/java/at/ac/uibk/gitsearch/repository/gitlab/GitLabRepository.java b/src/main/java/at/ac/uibk/gitsearch/repository/gitlab/GitLabRepository.java
index 02088a8a2d18f6e6742f3d09c050b3769c0e2263..1ce65020fc98edef7466d334657193a4920279b9 100644
--- a/src/main/java/at/ac/uibk/gitsearch/repository/gitlab/GitLabRepository.java
+++ b/src/main/java/at/ac/uibk/gitsearch/repository/gitlab/GitLabRepository.java
@@ -8,16 +8,20 @@ import java.util.stream.Stream;
 import org.gitlab4j.api.Constants.TokenType;
 import org.gitlab4j.api.GitLabApi;
 import org.gitlab4j.api.GitLabApiException;
+import org.gitlab4j.api.models.Group;
 import org.gitlab4j.api.models.Project;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public class GitLabRepository {
 
+  public static final String FULLPATH_OF_GROUP_CACHE = "fullPathOfGroupCache";
+
   @SuppressWarnings("unused")
   private final Logger log = LoggerFactory.getLogger(GitLabRepository.class);
 
@@ -95,4 +99,18 @@ public class GitLabRepository {
   public Stream<Project> streamAllProjects() throws GitLabApiException {
     return getAdminGitLabApi().getProjectApi().getProjectsStream();
   }
+
+  /**
+   * just a helper method, that caches the group namespaces
+   *
+   * @param gitLabApi
+   * @param groupId
+   * @return
+   * @throws GitLabApiException
+   */
+  @Cacheable(cacheNames = FULLPATH_OF_GROUP_CACHE)
+  public String getFullPathOfGroup(final Long groupId) throws GitLabApiException {
+    final Group group = getAdminGitLabApi().getGroupApi().getGroup(groupId);
+    return group.getFullPath();
+  }
 }
diff --git a/src/main/java/at/ac/uibk/gitsearch/repository/search/ElasticSearchRepository.java b/src/main/java/at/ac/uibk/gitsearch/repository/search/ElasticSearchRepository.java
index 2254b2aa208a711130893305bb3c85f5fe9dcbab..45b5645436ac51126030590b71e9ea6b90edcd53 100644
--- a/src/main/java/at/ac/uibk/gitsearch/repository/search/ElasticSearchRepository.java
+++ b/src/main/java/at/ac/uibk/gitsearch/repository/search/ElasticSearchRepository.java
@@ -24,6 +24,7 @@ import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
 import co.elastic.clients.elasticsearch.indices.update_aliases.AddAction;
 import java.io.IOException;
 import java.io.InputStream;
+import java.text.ParseException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
@@ -33,6 +34,7 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codeability.sharing.plugins.api.search.SearchResultDTO;
 import org.codeability.sharing.plugins.api.search.SearchStatisticsDTO;
+import org.codeability.sharing.plugins.api.search.util.ExerciseId;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Repository;
 
@@ -71,8 +73,21 @@ public class ElasticSearchRepository {
    * @throws IOException
    */
   public String index(final SearchResultDTO document, String index) throws IOException {
-    this.elasticsearchAPIClient.index(i -> i.index(index).id(document.getExerciseId()).document(document));
-    return document.getExerciseId();
+    this.elasticsearchAPIClient.index(i -> {
+        final String exerciseId = document.getExerciseId();
+        return i.index(index).id(exerciseId).document(document);
+      });
+    final String exerciseId2 = document.getExerciseId();
+    if (exerciseId2 == null) {
+      LOGGER.error("Somehow we got an empty exerciseId in {}", document);
+    } else {
+      try {
+        ExerciseId.fromString(exerciseId2);
+      } catch (ParseException e) {
+        LOGGER.error("Somehow we got an corrupt exerciseId {}", exerciseId2, e);
+      }
+    }
+    return exerciseId2;
   }
 
   public void waitForIndexingFinished() throws IOException {
@@ -147,9 +162,13 @@ public class ElasticSearchRepository {
    * @throws ElasticsearchException
    * @throws IOException
    */
+  @SuppressWarnings("null")
   public SearchResultDTO get(final String docId) throws IOException {
     final GetResponse<SearchResultDTO> searchResultDTOResponse =
       this.elasticsearchAPIClient.get(r -> r.index(SearchRepositoryConstants.INDEX_METADATA).id(docId), SearchResultDTO.class);
+    if (searchResultDTOResponse.source() != null) {
+      searchResultDTOResponse.source().setExerciseId(docId);
+    }
     return searchResultDTOResponse.source();
   }
 
diff --git a/src/main/java/at/ac/uibk/gitsearch/security/oauth2/UserDetailsFetcher.java b/src/main/java/at/ac/uibk/gitsearch/security/oauth2/UserDetailsFetcher.java
index e03a7e3e61db607d5d2bb34708e390be9d050d3f..9c4f010bed059b1ae32e43675fa1df9ecec1b393 100644
--- a/src/main/java/at/ac/uibk/gitsearch/security/oauth2/UserDetailsFetcher.java
+++ b/src/main/java/at/ac/uibk/gitsearch/security/oauth2/UserDetailsFetcher.java
@@ -1,6 +1,7 @@
 package at.ac.uibk.gitsearch.security.oauth2;
 
 import at.ac.uibk.gitsearch.domain.Authority;
+import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
 import at.ac.uibk.gitsearch.service.dto.AdminUserDTO;
 import java.time.Instant;
 import java.util.ArrayList;
@@ -11,6 +12,7 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.stream.Stream;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -20,7 +22,9 @@ import org.gitlab4j.api.GitLabApiException;
 import org.gitlab4j.api.models.ImpersonationToken;
 import org.gitlab4j.api.models.ImpersonationToken.Scope;
 import org.gitlab4j.api.models.Membership;
+import org.gitlab4j.api.models.MembershipSourceType;
 import org.gitlab4j.api.models.User;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 import org.springframework.stereotype.Component;
@@ -36,6 +40,9 @@ public class UserDetailsFetcher {
   @Value("${application.gitlab.url}")
   private String gitlabURI;
 
+  @Autowired
+  private GitLabRepository gitLabRepository;
+
   /**
    * just a holder class for the return of update User
    */
@@ -117,10 +124,7 @@ public class UserDetailsFetcher {
       }
       userToken = requestGitLabUserToken(gitUser, gitLabApi);
 
-      List<Membership> memberships = gitLabApi.getUserApi().getMemberships(gitUser.getId());
-      for (Membership membership : memberships) {
-        authorities.add(membership.getSourceName());
-      }
+      getUserMemberships(gitLabApi, gitUser).forEach(gitAuthority -> authorities.add(gitAuthority));
 
       modified |= updateAttribute(gitUser.getAvatarUrl(), u.getImageUrl(), u::setImageUrl);
       modified |= updateAttribute(gitUser.getEmail(), u.getEmail(), u::setEmail);
@@ -141,6 +145,36 @@ public class UserDetailsFetcher {
     return new UserDetailsInfo(userToken, modified);
   }
 
+  /**
+   * returns the pathes of all groups the user belongs to
+   *
+   * @param gitLabApi
+   * @param gitUser
+   * @return
+   */
+  public Stream<String> getUserMemberships(GitLabApi gitLabApi, User gitUser) {
+    List<Membership> memberships;
+    try {
+      memberships = gitLabApi.getUserApi().getMemberships(gitUser.getId());
+    } catch (GitLabApiException e) {
+      logger.warn("Cannot read group path for {}", gitUser);
+      return Stream.empty();
+    }
+    return memberships
+      .stream()
+      .filter(membership -> MembershipSourceType.NAMESPACE.equals(membership.getSourceType()))
+      .map(membership -> membership.getSourceId()) // map to group id
+      .map(groupId -> {
+        try {
+          return gitLabRepository.getFullPathOfGroup(groupId);
+        } catch (GitLabApiException e) {
+          logger.warn("Cannot read group path for {}", groupId);
+          return null;
+        }
+      })
+      .filter(path -> path != null);
+  }
+
   private String generatePassword() {
     return RandomStringUtils.random(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz=%$-.");
   }
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/StatisticsService.java b/src/main/java/at/ac/uibk/gitsearch/service/StatisticsService.java
index 98c444e9fb3cb73cf85c118cfbd66ebbbe735ea3..3ca27991a85bc6514b4c6d75a52df17f52d9c61b 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/StatisticsService.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/StatisticsService.java
@@ -4,6 +4,7 @@ import at.ac.uibk.gitsearch.domain.Statistics;
 import at.ac.uibk.gitsearch.repository.jpa.StatisticsRepository;
 import at.ac.uibk.gitsearch.repository.search.ElasticSearchRepository;
 import at.ac.uibk.gitsearch.service.dto.StatisticsDTO;
+import at.ac.uibk.gitsearch.service.mapper.StatisticsMapper;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -35,6 +36,9 @@ public class StatisticsService {
   @Autowired
   private ElasticSearchRepository elasticSearchRepository;
 
+  @Autowired
+  private StatisticsMapper statisticsMapper;
+
   /**
    * Save a statistics.
    *
@@ -231,7 +235,8 @@ public class StatisticsService {
       entry = statistics.get(statistics.size() - 1); // last one
     }
     updater.update(entry);
-    statisticsRepository.save(entry);
+    entry = statisticsRepository.save(entry);
+    updateSearchResult(statisticsMapper.toDto(entry));
   }
 
   public void removeBadgeForStatisticsByExerciseID(String exerciseID) {
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventService.java b/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventService.java
index 6285a3ba04b337ccd7f5f3dcca460dabcb282b3e..383111b7d731b7344c1c5f51e577ea073f6706bd 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventService.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventService.java
@@ -56,10 +56,12 @@ import org.gitlab4j.api.GitLabApi;
 import org.gitlab4j.api.GitLabApiException;
 import org.gitlab4j.api.models.Branch;
 import org.gitlab4j.api.models.Commit;
+import org.gitlab4j.api.models.Group;
 import org.gitlab4j.api.models.Member;
 import org.gitlab4j.api.models.Project;
 import org.gitlab4j.api.models.ProjectSharedGroup;
 import org.gitlab4j.api.models.RepositoryFile;
+import org.gitlab4j.api.models.SharedGroup;
 import org.gitlab4j.api.models.TreeItem;
 import org.gitlab4j.api.models.User;
 import org.gitlab4j.api.systemhooks.GroupSystemHookEvent;
@@ -581,24 +583,51 @@ public class GitlabEventService {
     ProjectPermissions result = new ProjectPermissions();
     adminGitLabApi.enableRequestResponseLogging(java.util.logging.Level.INFO);
     try {
-      for (Member member : adminGitLabApi.getProjectApi().getMembers(p.getId())) {
+      for (Member member : adminGitLabApi.getProjectApi().getAllMembers(p.getId())) {
         if (member.getEmail() == null) {
           // member does not show email address?
           User user = adminGitLabApi.getUserApi().getUser(member.getId());
-          result.emailAddressesWithAccess.add(user.getEmail());
+          result.addEmailWithAccess(user.getEmail());
         } else {
-          result.emailAddressesWithAccess.add(member.getEmail());
+          result.addEmailWithAccess(member.getEmail());
         }
       }
     } catch (GitLabApiException e) {
       logger.error("Cannot access members for {} ({})", p.getNameWithNamespace(), p.getId(), e);
     }
 
-    final List<ProjectSharedGroup> sharedWithGroups = p.getSharedWithGroups();
+    List<String> allGroups = getDirectAndIndirectGroups(p);
+    allGroups.forEach(group -> result.addGroupWithAccess(group));
+    return result;
+  }
+
+  @SuppressWarnings("deprecation")
+  protected List<String> getDirectAndIndirectGroups(Project p) {
+    final List<ProjectSharedGroup> sharedWithGroups = p.getSharedWithGroups(); // returns only direct groups
+    List<String> allGroups = new ArrayList<>();
     for (ProjectSharedGroup group : sharedWithGroups) {
-      result.groupsWithAccess.add(group.getGroupName());
+      allGroups.add(group.getGroupFullPath());
     }
-    return result;
+    allGroups.addAll(getDirectAndIndirectGroups(p.getNamespace().getId()));
+    return allGroups;
+  }
+
+  protected List<String> getDirectAndIndirectGroups(Long groupId) {
+    List<String> allGroups = new ArrayList<>();
+    try {
+      final Group group = adminGitLabApi.getGroupApi().getGroup(groupId);
+      if (group != null) {
+        final List<SharedGroup> sharedGroups = group.getSharedWithGroups();
+        sharedGroups.forEach(g -> allGroups.add(g.getGroupFullPath()));
+        final Long parentId = group.getParentId();
+        if (parentId != null) {
+          allGroups.addAll(getDirectAndIndirectGroups(parentId));
+        }
+      }
+    } catch (GitLabApiException e) {
+      logger.warn("Cannot retrieve subgroups of {}", groupId);
+    }
+    return allGroups;
   }
 
   public class Indexing {
@@ -635,8 +664,8 @@ public class GitlabEventService {
 
       gp.setArchived(p.getArchived());
       gp.setVisibility(p.getVisibility());
-      gp.setUsers(perm.getEmailAddressesWithAccess());
-      gp.setGroups(perm.getGroupsWithAccess());
+      gp.setUsers(new ArrayList<>(perm.getEmailAddressesWithAccess()));
+      gp.setGroups(new ArrayList<>(perm.getGroupsWithAccess()));
       gp.setOpen_issues_count(p.getOpenIssuesCount());
       gp.setForks_count(p.getForksCount());
       gp.setLast_activity_at(lastActivity);
diff --git a/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/ProjectPermissions.java b/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/ProjectPermissions.java
index 04a09f3d61b721f2d2ac77b3cb3aa14a4cad51c2..d101b0692c9ad240e69b7fd6259b13e05a7a8ede 100644
--- a/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/ProjectPermissions.java
+++ b/src/main/java/at/ac/uibk/gitsearch/service/gitlab_events/ProjectPermissions.java
@@ -1,18 +1,25 @@
 package at.ac.uibk.gitsearch.service.gitlab_events;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 public class ProjectPermissions {
 
-  final List<String> emailAddressesWithAccess = new ArrayList<>();
-  final List<String> groupsWithAccess = new ArrayList<>();
+  private final Set<String> emailAddressesWithAccess = new HashSet<>();
+  private final Set<String> groupsWithAccess = new HashSet<>();
 
-  public List<String> getEmailAddressesWithAccess() {
+  public void addEmailWithAccess(String email) {
+    this.emailAddressesWithAccess.add(email);
+  }
+
+  public void addGroupWithAccess(String group) {
+    this.groupsWithAccess.add(group);
+  }
+
+  public Set<String> getEmailAddressesWithAccess() {
     return emailAddressesWithAccess;
   }
 
-  public List<String> getGroupsWithAccess() {
+  public Set<String> getGroupsWithAccess() {
     return groupsWithAccess;
   }
 }
diff --git a/src/test/java/at/ac/uibk/gitsearch/repository/search/testESService/ElasticSearchTestConfiguration.java b/src/test/java/at/ac/uibk/gitsearch/repository/search/testESService/ElasticSearchTestConfiguration.java
index c9f2ee9e5add0b95295d32f707ca2d58b106fbde..6b8333448513c8fce61892f90579957d6ba8faaa 100644
--- a/src/test/java/at/ac/uibk/gitsearch/repository/search/testESService/ElasticSearchTestConfiguration.java
+++ b/src/test/java/at/ac/uibk/gitsearch/repository/search/testESService/ElasticSearchTestConfiguration.java
@@ -123,7 +123,7 @@ public class ElasticSearchTestConfiguration {
         }
       }
       esContainer = null;
-      LOGGER.warn("Shutted down ES Test Node");
+      LOGGER.warn("Shut down ES Test Node");
     }
   }
 
diff --git a/src/test/java/at/ac/uibk/gitsearch/service/AuditEventServiceIT.java b/src/test/java/at/ac/uibk/gitsearch/service/AuditEventServiceIT.java
index b13dc5f1b3c9f17822a0f2e951df09b68ea94023..abc8530ad26406cdb173594abf8962167df7fdc4 100644
--- a/src/test/java/at/ac/uibk/gitsearch/service/AuditEventServiceIT.java
+++ b/src/test/java/at/ac/uibk/gitsearch/service/AuditEventServiceIT.java
@@ -103,7 +103,7 @@ public class AuditEventServiceIT {
   @Test
   @Timeout(value = 5, unit = TimeUnit.MINUTES)
   @DirtiesContext
-  public void verifyOldAuditEventsAreDeleted() {
+  void verifyOldAuditEventsAreDeleted() {
     assertThat(persistenceAuditEventRepository.findAll().size()).isEqualTo(currentAuditLogs + auditEventsOld.size() + 2);
 
     log.info("Removing outdated AuditEvents");
@@ -124,7 +124,7 @@ public class AuditEventServiceIT {
   @Test
   @Timeout(value = 5, unit = TimeUnit.MINUTES)
   @DirtiesContext
-  public void verifyOldAuditEventsAreDeleted2() {
+  void verifyOldAuditEventsAreDeleted2() {
     assertThat(persistenceAuditEventRepository.findAll().size()).isEqualTo(currentAuditLogs + auditEventsOld.size() + 2);
 
     int deleted = this.auditEventService.removeOutdatedAuditEvents2();
diff --git a/src/test/java/at/ac/uibk/gitsearch/service/ReminderServiceIT.java b/src/test/java/at/ac/uibk/gitsearch/service/ReminderServiceIT.java
index 9ab54cae51bbaea12703d705d37d03f4897eab1f..47da511d0ccc1b4363903ff21033c86cfa8d4711 100644
--- a/src/test/java/at/ac/uibk/gitsearch/service/ReminderServiceIT.java
+++ b/src/test/java/at/ac/uibk/gitsearch/service/ReminderServiceIT.java
@@ -225,9 +225,7 @@ public class ReminderServiceIT {
     verify(mailService).sendEmail(toCaptor.capture(), subjectCaptor.capture(), messageCaptor.capture(), anyBoolean(), anyBoolean());
     assertThat(toCaptor.getValue()).contains(user.getEmail());
     final String content = messageCaptor.getValue();
-    assertThat(content).isNotEmpty();
-
-    assertThat(content).contains("Simple IO Test").contains("testDaily");
+    assertThat(content).isNotEmpty().contains("Simple IO Test").contains("testDaily");
 
     // last sending update?
     // for daily watch list
diff --git a/src/test/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventServiceIT.java b/src/test/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventServiceIT.java
index 9e2a84f95482c03fe2c6a20c6910ca016427a93b..dccf8270a975071419190f6aec4c25dc69a0c93f 100644
--- a/src/test/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventServiceIT.java
+++ b/src/test/java/at/ac/uibk/gitsearch/service/gitlab_events/GitlabEventServiceIT.java
@@ -10,6 +10,7 @@ import static org.mockito.Mockito.verify;
 import at.ac.uibk.gitsearch.GitsearchApp;
 import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository;
 import at.ac.uibk.gitsearch.repository.search.ElasticSearchRepository;
+import at.ac.uibk.gitsearch.repository.search.MetaDataRepository;
 import at.ac.uibk.gitsearch.repository.search.SearchRepositoryConstants;
 import at.ac.uibk.gitsearch.repository.search.testESService.ElasticSearchTestConfiguration;
 import at.ac.uibk.gitsearch.service.MailService;
@@ -28,8 +29,10 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Stream;
 import javax.el.MethodNotFoundException;
@@ -51,6 +54,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
 import org.springframework.security.test.context.support.WithMockUser;
 
 @SpringBootTest(classes = GitsearchApp.class)
@@ -67,6 +72,9 @@ public class GitlabEventServiceIT {
   @Autowired
   protected GitlabEventService eventService;
 
+  @Autowired
+  protected MetaDataRepository metaDataRepository;
+
   @MockBean
   private MailService mailService;
 
@@ -107,6 +115,7 @@ public class GitlabEventServiceIT {
       .thenReturn(Boolean.TRUE);
 
     logger.info("starting handleGitLabEvent for {}", collectionCommitEvent);
+
     eventService.handleGitLabEvent(collectionCommitEvent);
     eventService.waitForFinish();
     logger.info("finished handleGitLabEvent for {}", collectionCommitEvent);
@@ -114,6 +123,33 @@ public class GitlabEventServiceIT {
     // the example is correct :-)
     verify(mailService, Mockito.times(1))
       .sendEmail(Mockito.eq("Michael.Breu@uibk.ac.at"), Mockito.anyString(), Mockito.anyString(), Mockito.eq(false), Mockito.eq(true));
+
+    // just reindex a second time, in order to check returned gitlab Id
+    eventService.handleGitLabEvent(collectionCommitEvent);
+    eventService.waitForFinish();
+  }
+
+  @Test
+  @Timeout(value = 30, unit = TimeUnit.MINUTES)
+  @WithMockUser(value = "Michael Breu", authorities = "teacher/unauthenticatedteachers")
+  void simplePermissionTest() throws StreamReadException, DatabindException, IOException, GitLabApiException, ParseException {
+    SystemHookEvent permissionCommitEvent = getPermissionCommitEvent();
+    Mockito.reset(mailService);
+    Mockito
+      .when(mailService.sendEmail(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(false), Mockito.eq(true)))
+      .thenReturn(Boolean.TRUE);
+
+    logger.info("starting permissionCommitEvent for {}", permissionCommitEvent);
+    eventService.handleGitLabEvent(permissionCommitEvent);
+    eventService.waitForFinish();
+
+    User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    metaDataRepository.getExerciseById("[274]", Optional.of(user));
+
+    final SearchResultDTO exercise = metaDataRepository.getExerciseById("[274]", Optional.of(user));
+    logger.info("finished permissionCommitEvent for {}", exercise);
+    assertThat(exercise.getProject().getGroups()).contains("teacher", "teacher/unauthenticatedteachers");
+    assertThat(exercise.getProject().getUsers()).contains("simon.priller@uibk.ac.at");
   }
 
   @Test
@@ -190,6 +226,11 @@ public class GitlabEventServiceIT {
     return getTestSystemHookEvent(testEvent);
   }
 
+  private SystemHookEvent getPermissionCommitEvent() throws IOException {
+    final String testEvent = "testData/gitlabEvents/testInheritedPermissions.json";
+    return getTestSystemHookEvent(testEvent);
+  }
+
   private SystemHookEvent getMetaData5PushEvent() throws IOException {
     final String testEvent = "testData/gitlabEvents/metadataVersion5Test.json";
     return getTestSystemHookEvent(testEvent);
@@ -208,7 +249,7 @@ public class GitlabEventServiceIT {
   }
 
   @Test
-  @Timeout(value = 30, unit = TimeUnit.MINUTES)
+  @Timeout(value = 1, unit = TimeUnit.MINUTES)
   void simpleDeleteTest() throws StreamReadException, DatabindException, IOException, GitLabApiException, InterruptedException {
     assertThat(gitLabRepository.getAdminGitLabApi().getAuthToken())
       .describedAs("This test requires a valid admin access token")
diff --git a/src/test/resources/at/ac/uibk/gitsearch/service/gitlab_events/testData/gitlabEvents/testInheritedPermissions.json b/src/test/resources/at/ac/uibk/gitsearch/service/gitlab_events/testData/gitlabEvents/testInheritedPermissions.json
new file mode 100644
index 0000000000000000000000000000000000000000..033e483d1c1a2a53d413571204f7daa6aefd82cb
--- /dev/null
+++ b/src/test/resources/at/ac/uibk/gitsearch/service/gitlab_events/testData/gitlabEvents/testInheritedPermissions.json
@@ -0,0 +1,60 @@
+{
+  "object_kind": "push",
+  "event_name": "push",
+  "before": "293b550d6089447f6b62b9a6abf7c318ec05cf86",
+  "after": "3baca63e5f21cf3cb680bce63bdeb34c6772f140",
+  "ref": "refs/heads/master",
+  "checkout_sha": "f9fbd3d3b520a3e59661f1806871db89294778de",
+  "message": null,
+  "user_id": 35,
+  "user_name": "Michael Breu",
+  "user_username": "c703257",
+  "user_email": "Michael.Breu@uibk.ac.at",
+  "user_avatar": "https://www.gravatar.com/avatar/ff28e10268b8c177179e17f11fd30357?s=80\u0026d=identicon",
+  "project_id": 274,
+  "project": {
+    "id": 274,
+    "name": "irrelvant",
+    "description": "",
+    "web_url": "https://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/test1",
+    "avatar_url": null,
+    "git_ssh_url": "git@sharing.codeability-austria.uibk.ac.at:sharing/health-check-tests/collection_tests/testit2.git",
+    "git_http_url": "https://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/test1.git",
+    "namespace": "sharing/health-check-tests/collection_tests",
+    "visibility_level": 0,
+    "path_with_namespace": "sharing/health-check-tests/collection_tests/testit2",
+    "default_branch": "master",
+    "ci_config_path": null,
+    "homepage": "http://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/testit2",
+    "url": "git@sharing.codeability-austria.uibk.ac.at:sharing/health-check-tests/collection_tests/testit2.git",
+    "ssh_url": "git@sharing.codeability-austria.uibk.ac.at:sharing/health-check-tests/collection_tests/testit2.git",
+    "http_url": "http://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/testit2.git"
+  },
+  "commits": [
+    {
+      "id": "3baca63e5f21cf3cb680bce63bdeb34c6772f140",
+      "message": "irrelevant: Update metadata.yaml",
+      "title": "irrelevant: Update metadata.yaml",
+      "timestamp": "2022-01-20T16:48:43+00:00",
+      "url": "https://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/collectionstests1/-/commit/293b550d6089447f6b62b9a6abf7c318ec05cf86",
+      "author": {
+        "name": "Michael Breu",
+        "email": "Michael.Breu@uibk.ac.at"
+      },
+      "added": [],
+      "modified": ["metadata.yaml"],
+      "removed": []
+    }
+  ],
+  "total_commits_count": 1,
+  "push_options": {},
+  "repository": {
+    "name": "CollectionTests1",
+    "url": "git@sharing.codeability-austria.uibk.ac.at:sharing/health-check-tests/collection_tests/collectionstests1.git",
+    "description": "",
+    "homepage": "http://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/testit2",
+    "git_http_url": "http://sharing.codeability-austria.uibk.ac.at/sharing/health-check-tests/collection_tests/testit2.git",
+    "git_ssh_url": "git@sharing.codeability-austria.uibk.ac.at:sharing/health-check-tests/collection_tests/testit2.git",
+    "visibility_level": 0
+  }
+}
diff --git a/src/test/sopaui/Sharing-Gitlab-Prod-soapui-project.xml b/src/test/sopaui/Sharing-Gitlab-Prod-soapui-project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e707e640d55c7ff25abf6fec09974a43600b1f38
--- /dev/null
+++ b/src/test/sopaui/Sharing-Gitlab-Prod-soapui-project.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<con:soapui-project id="f15cb322-bca1-4f72-94c0-edce59dcf5e1" activeEnvironment="Default" name="Sharing Gitlab Prod" resourceRoot="" soapui-version="5.7.2" xmlns:con="http://eviware.com/soapui/config"><con:settings/><con:interface xsi:type="con:RestService" id="cab275c1-0fcf-470f-a5e4-6cfa80e2eec9" wadlVersion="http://wadl.dev.java.net/2009/02" name="https://sharing-codeability.uibk.ac.at" type="rest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><con:settings/><con:definitionCache type="TEXT" rootPart=""/><con:endpoints><con:endpoint>https://sharing.codeability-austria.uibk.ac.at/api/v4</con:endpoint></con:endpoints><con:resource name="V4" path="/projects" id="219fb6b8-a1f2-4965-9e2e-ca42658fb80f"><con:settings/><con:parameters/><con:method name="V4 1" id="75d86bf4-6a49-4828-bc5c-3ea3a4dbb779" method="GET"><con:settings/><con:parameters/><con:representation type="RESPONSE"><con:mediaType>application/json</con:mediaType><con:status>200</con:status><con:params/><con:element>Response</con:element></con:representation><con:request name="Request 1" id="464de6e2-84ca-4136-af01-ef5a83c0867a" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting></con:settings><con:endpoint>https://sharing.codeability-austria.uibk.ac.at/api/v4</con:endpoint><con:request/><con:originalUri>https://sharing-codeability.uibk.ac.at/api/v4/projects</con:originalUri><con:credentials><con:username xsi:nil="true"/><con:password xsi:nil="true"/><con:domain xsi:nil="true"/><con:authType>No Authorization</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:request></con:method></con:resource><con:resource name="groups" path="/groups" id="dfc85de8-6522-4915-ac69-467c1406bc0a"><con:settings/><con:parameters/><con:method name="Method 1" id="ad310c54-c143-4d59-99d2-ba1efbe6b599" method="GET"><con:settings/><con:parameters/><con:representation type="RESPONSE"><con:mediaType>application/json</con:mediaType><con:status>200</con:status><con:params/><con:element>Response</con:element></con:representation><con:representation type="FAULT"><con:mediaType>application/json</con:mediaType><con:status>404</con:status><con:params/><con:element xmlns:gro="https://sharing-codeability.uibk.ac.at/api/v4/groups">gro:Fault</con:element></con:representation><con:request name="All Requests" id="e0aebed2-0440-4442-8641-781416db5140" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting></con:settings><con:endpoint>https://sharing.codeability-austria.uibk.ac.at/api/v4</con:endpoint><con:request/><con:originalUri>https://sharing-codeability.uibk.ac.at/api/v4/groups</con:originalUri><con:credentials><con:username xsi:nil="true"/><con:password xsi:nil="true"/><con:domain xsi:nil="true"/><con:authType>No Authorization</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:request><con:request name="GroupMembers" id="e0aebed2-0440-4442-8641-781416db5140" mediaType="application/json"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.WsdlRequest@request-headers">&lt;xml-fragment/></con:setting></con:settings><con:endpoint>https://sharing.codeability-austria.uibk.ac.at/api/v4</con:endpoint><con:request/><con:originalUri>https://sharing-codeability.uibk.ac.at/api/v4/groups</con:originalUri><con:credentials><con:username xsi:nil="true"/><con:password xsi:nil="true"/><con:domain xsi:nil="true"/><con:authType>No Authorization</con:authType></con:credentials><con:jmsConfig JMSDeliveryMode="PERSISTENT"/><con:jmsPropertyConfig/><con:parameters/></con:request></con:method></con:resource></con:interface><con:properties><con:property><con:name>adminToken</con:name><con:value>glpat-HY-7PxnrfWfnE6WvX4YK</con:value></con:property></con:properties><con:wssContainer/><con:oAuth2ProfileContainer/><con:oAuth1ProfileContainer/><con:sensitiveInformation/></con:soapui-project>
\ No newline at end of file