From 4c8621cedfafef03dc520e97a84f67f5b80e7c1c Mon Sep 17 00:00:00 2001
From: RIHTARSIC Joze <joze.rihtarsic@ext.ec.europa.eu>
Date: Sat, 20 May 2023 16:55:03 +0200
Subject: [PATCH] Fix group visibility and add visibility description to
 resource data panel

---
 .../smp-warning-panel.component.html          |   2 +-
 .../resource-details-panel.component.html     |  12 +-
 .../resource-details-panel.component.ts       |  16 +-
 .../ec/edelivery/smp/data/dao/QueryNames.java |   5 +
 .../edelivery/smp/data/dao/ResourceDao.java   |  20 ++-
 .../smp/data/model/doc/DBResource.java        |  51 +++---
 .../smp/data/model/doc/DBResourceFilter.java  |  13 ++
 .../ResourceDaoMembershipIntegrationTest.java |   1 -
 .../smp/data/dao/ResourceDaoSearchTest.java   |  76 +++++---
 .../edelivery/smp/data/dao/TestUtilsDao.java  | 165 ++++++++++++------
 .../edelivery/smp/testutil/TestConstants.java |   2 +
 .../edelivery/smp/testutil/TestDBUtils.java   |   6 +-
 12 files changed, 256 insertions(+), 113 deletions(-)

diff --git a/smp-angular/src/app/common/components/smp-warning-panel/smp-warning-panel.component.html b/smp-angular/src/app/common/components/smp-warning-panel/smp-warning-panel.component.html
index 43c228c8e..8be89d856 100644
--- a/smp-angular/src/app/common/components/smp-warning-panel/smp-warning-panel.component.html
+++ b/smp-angular/src/app/common/components/smp-warning-panel/smp-warning-panel.component.html
@@ -5,6 +5,6 @@
   'alert-warning': type === 'warning',
   'alert-error':  type === 'error'}"
 >
-  <mat-icon *ngIf="icon">{{icon}}</mat-icon>
+  <mat-icon *ngIf="icon" style="width:50px">{{icon}}</mat-icon>
   <span>{{label}}</span>
 </div>
diff --git a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
index 22a65f3d7..8d0ac6a5e 100644
--- a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
+++ b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
@@ -41,9 +41,8 @@
       >
     </mat-form-field>
     <mat-form-field style="width:100%">
-      <mat-label>Group visibility</mat-label>
-      <mat-select placeholder="Resource visibility"
-                  formControlName="visibility"
+      <mat-label>Resource visibility</mat-label>
+      <mat-select formControlName="visibility"
                   matTooltip="Resource visibility."
                   id="visibility_id" required>
         <mat-option *ngFor="let visibility of groupVisibilityOptions"
@@ -51,8 +50,13 @@
           {{visibility.key}}
         </mat-option>
       </mat-select>
-      <mat-hint>Choose resource visibility</mat-hint>
     </mat-form-field>
+
+    <smp-warning-panel
+      type="desc"
+      icon="info"
+      [label]="visibilityDescription"
+    ></smp-warning-panel>
   </form>
 
 </div>
diff --git a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
index c95ad7234..3b140de79 100644
--- a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
+++ b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
@@ -30,7 +30,6 @@ export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
   @Input() domain: DomainRo;
   @Input() domainResourceDefs: ResourceDefinitionRo[];
 
-
   resourceForm: FormGroup;
 
 
@@ -82,8 +81,6 @@ export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
     let node:NavigationNode = this.createNew();
     this.navigationService.selected.children = [node]
     this.navigationService.select(node);
-
-
   }
 
   public createNew():NavigationNode{
@@ -101,6 +98,19 @@ export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
   isDirty(): boolean {
     return false;
   }
+
+  get visibilityDescription(): string {
+    if (this.resourceForm.get('visibility').value == VisibilityEnum.Private) {
+      return "The private resource is accessible only to the resource members!"
+    }
+    if (this.group.visibility == VisibilityEnum.Private) {
+      return "The resource belongs to the private group. The resource is accessible only to the members of the group (direct and indirect group members)!"
+    }
+    if (this.domain.visibility == VisibilityEnum.Private) {
+      return "The resource belongs to the private domain. The resource is accessible only to the members of the domain (direct and indirect domain members)!"
+    }
+    return "The resource is public on the public group and the public domain. The resource data is accessible to all users."
+  }
 }
 
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
index 39a88555e..5e843362e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
@@ -62,6 +62,11 @@ public class QueryNames {
     public static final String QUERY_RESOURCES_BY_DOMAIN_ID_COUNT = "DBResource.getResByDomainIdCount";
     public static final String QUERY_RESOURCES_BY_DOMAIN_ID_RESOURCE_DEF_ID_COUNT = "DBResource.getResByDomainIdAndResourceDefCount";
 
+
+    public static final String QUERY_RESOURCE_ALL_FOR_USER = "DBResource.getPublicSearch";
+
+    public static final String QUERY_RESOURCE_ALL_FOR_USER_COUNT = "DBResource.getPublicSearchCount";
+
     public static final String QUERY_RESOURCE_FILTER = "DBResource.getResourcesByFilter";
     public static final String QUERY_RESOURCE_FILTER_COUNT = "DBResource.getResourcesByFilterCount";
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
index eca074ce5..9cd8a65d4 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
@@ -58,6 +58,7 @@ public class ResourceDao extends BaseDao<DBResource> {
      * @return DBResource from the database
      */
     public Optional<DBResource> getResource(String identifierValue, String identifierSchema, DBResourceDef resourceDef, DBDomain domain) {
+        LOG.debug("Get resource (identifier [{}], scheme [{}])", identifierValue, identifierSchema);
         try {
             TypedQuery<DBResource> query = memEManager.createNamedQuery(QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN, DBResource.class);
             query.setParameter(PARAM_DOMAIN_ID, domain.getId());
@@ -75,6 +76,7 @@ public class ResourceDao extends BaseDao<DBResource> {
 
 
     public Long getResourcesForFilterCount(DBResourceFilter resourceFilter) {
+        LOG.debug("Get resources count for filter [{}]", resourceFilter);
 
         TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_FILTER_COUNT, Long.class);
         query.setParameter(PARAM_GROUP_ID, resourceFilter.getGroupId());
@@ -87,7 +89,7 @@ public class ResourceDao extends BaseDao<DBResource> {
     }
 
     public List<DBResource> getResourcesForFilter(int iPage, int iPageSize, DBResourceFilter resourceFilter) {
-
+        LOG.debug("Get resources page [{}] and page size [{}] for filter [{}]", iPage, iPageSize, resourceFilter);
         TypedQuery<DBResource> query = memEManager.createNamedQuery(QUERY_RESOURCE_FILTER, DBResource.class);
 
         if (iPageSize > -1 && iPage > -1) {
@@ -107,7 +109,9 @@ public class ResourceDao extends BaseDao<DBResource> {
     }
 
     public List<DBResource> getPublicResourcesSearch(int iPage, int iPageSize, DBUser user, String schema, String identifier) {
-        TypedQuery<DBResource> query = memEManager.createNamedQuery("DBResource.getPublicSearch", DBResource.class);
+        LOG.debug("Get resources for user [{}]", user);
+
+        TypedQuery<DBResource> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER, DBResource.class);
         if (iPageSize > -1 && iPage > -1) {
             query.setFirstResult(iPage * iPageSize);
         }
@@ -115,18 +119,19 @@ public class ResourceDao extends BaseDao<DBResource> {
             query.setMaxResults(iPageSize);
         }
         query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null);
-        query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema)? null: StringUtils.wrapIfMissing(schema,"%"));
-        query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier)? null: StringUtils.wrapIfMissing(identifier,"%"));
+        query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema) ? null : StringUtils.wrapIfMissing(schema, "%"));
+        query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier) ? null : StringUtils.wrapIfMissing(identifier, "%"));
 
         return query.getResultList();
     }
 
     public Long getPublicResourcesSearchCount(DBUser user, String schema, String identifier) {
-        TypedQuery<Long> query = memEManager.createNamedQuery("DBResource.getPublicSearchCount", Long.class);
+        LOG.debug("Get resources count for user [{}]", user);
+        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER_COUNT, Long.class);
 
         query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null);
-        query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema)? null: StringUtils.wrapIfMissing(schema,"%"));
-        query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier)? null: StringUtils.wrapIfMissing(identifier,"%"));
+        query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema) ? null : StringUtils.wrapIfMissing(schema, "%"));
+        query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier) ? null : StringUtils.wrapIfMissing(identifier, "%"));
 
         return query.getSingleResult();
     }
@@ -245,7 +250,6 @@ public class ResourceDao extends BaseDao<DBResource> {
             }
             lstResult = q.getResultList();
         } catch (NoResultException ex) {
-            //LOG.warn("No result for '" + filterType.getName() + "' does not have a setter!", ex);
             lstResult = new ArrayList<>();
         }
         return lstResult;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
index 2b97648c7..4bdb5be07 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResource.java
@@ -73,7 +73,7 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @NamedNativeQuery(name = "DBResource.deleteAllOwnerships", query = "DELETE FROM SMP_RESOURCE_MEMBER WHERE FK_SG_ID=:serviceGroupId")
 
 // get All public
-@NamedQuery(name = "DBResource.getPublicSearch", query = "SELECT r FROM  DBResource r WHERE r.group.visibility='PUBLIC' " +
+@NamedQuery(name = "DBResource.getPublicSearch2", query = "SELECT r FROM  DBResource r WHERE r.group.visibility='PUBLIC' " +
         " AND (r.group.domain.visibility='PUBLIC' " +
         "    OR :user_id IS NOT NULL " +
         "     AND ( (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " +
@@ -93,25 +93,36 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
         " AND (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier )" +
         " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme) order by r.identifierScheme, r.identifierValue"
 )
-@NamedQuery(name = "DBResource.getPublicSearchCount", query = "SELECT count(r.id) FROM  DBResource r WHERE r.group.visibility='PUBLIC' " +
-        " AND (r.group.domain.visibility='PUBLIC' " +
-        "    OR :user_id IS NOT NULL " +
-        "     AND ( (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " +
-        "      OR (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.domain.id = r.group.domain.id) > 0 " +
-        "      OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.domain.id = r.group.domain.id) > 0 " +
-        "     ) " +
-        "  ) " +
-        " AND (r.group.visibility='PUBLIC' " +
-        "    OR  :user_id IS NOT NULL " +
-        "     AND ( (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.id = r.group.id) > 0 " +
-        "      OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.id = r.group.id) > 0 " +
-        "     ) " +
-        "  ) " +
-        " AND ( r.visibility = 'PUBLIC' " +
-        "   OR :user_id IS NOT NULL " +
-        "     AND (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.id = r.id) > 0 ) " +
-        " AND (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier )" +
-        " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme)"
+@NamedQuery(name = QUERY_RESOURCE_ALL_FOR_USER, query = "SELECT DISTINCT r FROM  DBResource r LEFT JOIN DBResourceMember rm ON r.id = rm.resource.id WHERE " +
+        " (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier) " +
+        " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme) " +
+        " AND :user_id IS NOT NULL AND rm.user.id = :user_id "  +
+        " OR  r.visibility ='PUBLIC' " + // user must be member of the group or the group is public
+        "   AND (:user_id IS NOT NULL " +
+        "         AND  ((select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = r.group.id) > 0 " +
+        "            OR  (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.id = r.group.id) > 0) " +
+        "       OR  r.group.visibility = 'PUBLIC'  " +
+        "           AND (r.group.domain.visibility = 'PUBLIC' " +
+        "            OR  (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " +
+        "            OR (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.domain.id = r.group.domain.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.domain.id = r.group.domain.id) > 0 " +
+        "))"+
+        "order by r.identifierScheme, r.identifierValue"
+)
+@NamedQuery(name = QUERY_RESOURCE_ALL_FOR_USER_COUNT, query = "SELECT count(distinct r.id) FROM  DBResource r LEFT JOIN DBResourceMember rm ON r.id = rm.resource.id WHERE " +
+        " (:resource_identifier IS NULL OR r.identifierValue like :resource_identifier) " +
+        " AND (:resource_scheme IS NULL OR r.identifierScheme like :resource_scheme) " +
+        " AND :user_id IS NOT NULL AND rm.user.id = :user_id "  +
+        " OR  r.visibility ='PUBLIC' " + // user must be member of the group or the group is public
+        "   AND (:user_id IS NOT NULL " +
+        "         AND  ((select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = r.group.id) > 0 " +
+        "            OR  (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.id = r.group.id) > 0) " +
+        "       OR  r.group.visibility = 'PUBLIC'  " +
+        "           AND (r.group.domain.visibility = 'PUBLIC' " +
+        "            OR  (select count(dm.id) from DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = r.group.domain.id) > 0 " +
+        "            OR (select count(gm.id) from DBGroupMember gm where gm.user.id = :user_id and gm.group.domain.id = r.group.domain.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.group.domain.id = r.group.domain.id) > 0 " +
+        "))"
 )
 public class DBResource extends BaseEntity {
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResourceFilter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResourceFilter.java
index 110319adb..99dda9fc4 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResourceFilter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBResourceFilter.java
@@ -75,6 +75,19 @@ public class DBResourceFilter {
         return user == null ? null : user.getId();
     }
 
+
+    @Override
+    public String toString() {
+        return "DBResourceFilter{" +
+                "user=" + user +
+                ", membershipRoleType=" + membershipRoleType +
+                ", resourceDef=" + resourceDef +
+                ", group=" + group +
+                ", domain=" + domain +
+                ", identifierFilter='" + identifierFilter + '\'' +
+                '}';
+    }
+
     public static Builder createBuilder() {
         return new Builder();
     }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoMembershipIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoMembershipIntegrationTest.java
index dfe2bc7b9..cd87005d2 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoMembershipIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoMembershipIntegrationTest.java
@@ -65,7 +65,6 @@ public class ResourceDaoMembershipIntegrationTest extends AbstractResourceDaoTes
         for (String username : usernames) {
             Optional<DBUser> user = userDao.findUserByUsername(username);
             DBResourceMember member = testUtilsDao.createResourceMembership(MembershipRoleType.ADMIN, user.get(), resource);
-            resourceMemberDao.persistFlushDetach(member);
             resource.getMembers().add(member);
         }
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
index 2f3da56a5..a9b6c47f4 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
@@ -1,27 +1,18 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
 
-import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
-import eu.europa.ec.edelivery.smp.data.model.DBDomain;
-import eu.europa.ec.edelivery.smp.data.model.DBGroup;
-import eu.europa.ec.edelivery.smp.data.model.doc.DBDocument;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResourceFilter;
-import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
-import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
-import eu.europa.ec.edelivery.smp.testutil.TestDBUtils;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 
-import javax.transaction.Transactional;
 import java.util.List;
-import java.util.Optional;
-
-import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*;
+import java.util.stream.Collectors;
 
 /**
  * Purpose of class is to test all resource methods with database.
@@ -40,35 +31,74 @@ public class ResourceDaoSearchTest extends AbstractBaseDao {
     public void prepareDatabase() {
         // setup initial data!
         testUtilsDao.clearData();
-        testUtilsDao.createResourcePrivateInternalMemberships();
-
-
+        testUtilsDao.createResourcesForSearch();
     }
 
     @Test
+    @Transactional
     public void getAllPublicResources() {
+        List<DBResource> allResources = testInstance.getResourcesForFilter(-1, -1, DBResourceFilter.createBuilder().build());
+        Assert.assertEquals(8, allResources.size());
+
+        // only one group is public -
         List<DBResource> result = testInstance.getPublicResourcesSearch(-1,-1,null, null, null);
-        //System.out.println(result.get(0));
-        Assert.assertEquals(2, result.size());
+        Assert.assertEquals(1, result.size());
+        assertResources(result, "1-1-1::pubPubPub");
 
+        // user1 (admin) and user2 (viewer) are members of all resources
+        result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser1(), null, null);
+        Assert.assertEquals(8, result.size());
 
-       result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser1(), null, null);
-        //System.out.println(result.get(0));
-        Assert.assertEquals(3, result.size());
+        result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser2(), null, null);
+        Assert.assertEquals(8, result.size());
+
+        // user3 is direct member of private domain - can see only public resource on public groups
+        result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser3(), null, null);
+        assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub");
+
+        // user4 is direct member of private group in private domain
+        result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser4(), null, null);
+        assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub", "7-7-7::privPrivPub");
+
+        // user5 is direct member of private resource in  private group in private domain
+        result = testInstance.getPublicResourcesSearch(-1,-1,testUtilsDao.getUser5(), null, null);
+        assertResources(result, "1-1-1::pubPubPub", "5-5-5::privPubPub", "7-7-7::privPrivPub", "8-8-8::privPrivPriv");
+    }
 
+    public void assertResources(List<DBResource> result, String ... resourceIdentifiers) {
+        List<String> resultIdentifiers = result.stream().map(val-> val.getIdentifierScheme()+"::"+val.getIdentifierValue() ).collect(Collectors.toList());
+        System.out.println(resultIdentifiers);
+        Assert.assertArrayEquals(resourceIdentifiers, resultIdentifiers.stream().toArray());
     }
 
     @Test
     public void getAllPublicResourcesCount() {
-        Long result = testInstance.getPublicResourcesSearchCount(null, null, null);
-        //System.out.println(result.get(0));
-        Assert.assertEquals(2, result.intValue());
+        List<DBResource> allResources = testInstance.getResourcesForFilter(-1, -1, DBResourceFilter.createBuilder().build());
+        Assert.assertEquals(8, allResources.size());
 
+        // only one group is public -
+        Long result = testInstance.getPublicResourcesSearchCount(null, null, null);
+        Assert.assertEquals(1, result.intValue());
 
+        // user1 (admin) and user2 (viewer) are members of all resources
         result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser1(), null, null);
-        //System.out.println(result.get(0));
+        Assert.assertEquals(8, result.intValue());
+
+        result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser2(), null, null);
+        Assert.assertEquals(8, result.intValue());
+
+        // user3 is direct member of private domain - can see only public resource on public groups
+        result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser3(), null, null);
+        Assert.assertEquals(2, result.intValue());
+
+        // user4 is direct member of private group in private domain
+        result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser4(), null, null);
         Assert.assertEquals(3, result.intValue());
 
+        // user5 is direct member of private resource in  private group in private domain
+        result = testInstance.getPublicResourcesSearchCount(testUtilsDao.getUser5(), null, null);
+        Assert.assertEquals(4, result.intValue());
+
     }
 
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
index e54128c02..a8f1e985e 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
@@ -56,6 +56,9 @@ public class TestUtilsDao {
     DBUser user2;
     DBUser user3;
 
+    DBUser user4;
+    DBUser user5;
+
     DBGroup groupD1G1;
     DBGroup groupD1G2;
     DBGroup groupD2G1;
@@ -83,6 +86,8 @@ public class TestUtilsDao {
 
     DBExtension extension;
 
+    boolean searchDataCreated = false;
+
     /**
      * Database can be cleaned by script before the next test; clean also the objects
      */
@@ -98,6 +103,8 @@ public class TestUtilsDao {
         user1 = null;
         user2 = null;
         user3 = null;
+        user4 = null;
+        user5 = null;
         groupD1G1 = null;
         groupD1G2 = null;
         groupD2G1 = null;
@@ -120,6 +127,8 @@ public class TestUtilsDao {
         //resourceInternalD1G1RD1 = null;
 
         extension = null;
+        searchDataCreated = false;
+
     }
 
 
@@ -204,13 +213,20 @@ public class TestUtilsDao {
         user1 = createDBUserByUsername(USERNAME_1);
         user2 = createDBUserByCertificate(USER_CERT_2);
         user3 = createDBUserByUsername(USERNAME_3);
+        user4 = createDBUserByUsername(USERNAME_4);
+        user5 = createDBUserByUsername(USERNAME_5);
+
         persistFlushDetach(user1);
         persistFlushDetach(user2);
         persistFlushDetach(user3);
+        persistFlushDetach(user4);
+        persistFlushDetach(user5);
 
         assertNotNull(user1.getId());
         assertNotNull(user2.getId());
         assertNotNull(user3.getId());
+        assertNotNull(user4.getId());
+        assertNotNull(user5.getId());
     }
 
     /**
@@ -228,12 +244,6 @@ public class TestUtilsDao {
         createUsers();
         domainMemberU1D1Admin = createDomainMembership(MembershipRoleType.ADMIN, user1, d1);
         domainMemberU1D2Viewer = createDomainMembership(MembershipRoleType.VIEWER, user1, d2);
-
-        persistFlushDetach(domainMemberU1D1Admin);
-        persistFlushDetach(domainMemberU1D2Viewer);
-
-        assertNotNull(domainMemberU1D1Admin.getId());
-        assertNotNull(domainMemberU1D2Viewer.getId());
     }
 
     @Transactional
@@ -246,12 +256,6 @@ public class TestUtilsDao {
         createUsers();
         groupMemberU1D1G1Admin = createGroupMembership(MembershipRoleType.ADMIN, user1, groupD1G1);
         groupMemberU1D2G1Viewer = createGroupMembership(MembershipRoleType.VIEWER, user1, groupD2G1);
-
-        persistFlushDetach(groupMemberU1D1G1Admin);
-        persistFlushDetach(groupMemberU1D2G1Viewer);
-
-        assertNotNull(groupMemberU1D1G1Admin.getId());
-        assertNotNull(groupMemberU1D2G1Viewer.getId());
     }
 
     @Transactional
@@ -264,71 +268,97 @@ public class TestUtilsDao {
         createResources();
         resourceMemberU1R1_D2G1RD1_Admin = createResourceMembership(MembershipRoleType.ADMIN, user1, resourceD1G1RD1);
         resourceMemberU1R2_D2G1RD1_Viewer = createResourceMembership(MembershipRoleType.VIEWER, user1, resourceD2G1RD1);
-
-
-        persistFlushDetach(resourceMemberU1R1_D2G1RD1_Admin);
-        persistFlushDetach(resourceMemberU1R2_D2G1RD1_Viewer);
-
-        assertNotNull(resourceMemberU1R1_D2G1RD1_Admin.getId());
-        assertNotNull(resourceMemberU1R2_D2G1RD1_Viewer.getId());
     }
 
     @Transactional
-    public void createResourcePrivateInternalMemberships() {
-        if (resourcePrivateD1G1RD1 != null) {
-            LOG.trace("privateInternalMemberships are already initialized!");
+    public void createResourcesForSearch() {
+
+        if (searchDataCreated) {
+            LOG.trace("Search Data is already initialized!");
             return;
         }
-        createResourceMemberships();
 
-        resourcePrivateD1G1RD1 = TestDBUtils.createDBResource(TEST_SG_ID_1+"Private", TEST_SG_SCHEMA_1, true);
-        resourcePrivateD1G1RD1.setVisibility(VisibilityType.PRIVATE);
-        resourcePrivateD1G1RD1.setGroup(groupD1G1);
-        resourcePrivateD1G1RD1.setDomainResourceDef(domainResourceDefD1R1);
-        /*
-        resourceInternalD1G1RD1 = TestDBUtils.createDBResource(TEST_SG_ID_1+"Internal", TEST_SG_SCHEMA_1, true);
-        resourceInternalD1G1RD1.setVisibility(VisibilityType.PRIVATE);
-        resourceInternalD1G1RD1.setGroup(groupD1G1);
-        resourceInternalD1G1RD1.setDomainResourceDef(domainResourceDefD1R1);
+        createUsers();
+        createResourceDefinitions();
+
+        DBDomain publicDomain = createDomain("publicDomain", VisibilityType.PUBLIC);
+        DBDomain privateDomain = createDomain("privateDomain", VisibilityType.PRIVATE);
 
-         */
+        DBDomainResourceDef publicDomainResourceDef = registerDomainResourceDefinition(publicDomain, resourceDefSmp);
+        DBDomainResourceDef privateDomainResourceDef= registerDomainResourceDefinition(privateDomain, resourceDefSmp);
+        // membership of the domain
+        createDomainMembership(MembershipRoleType.VIEWER, user3, privateDomain);
 
-        //persistFlushDetach(resourceInternalD1G1RD1);
-        persistFlushDetach(resourcePrivateD1G1RD1);
+        DBGroup pubPubGroup = createGroup("pubPubGroup", VisibilityType.PUBLIC, publicDomain);
+        DBGroup pubPrivGroup = createGroup("pubPrivGroup", VisibilityType.PRIVATE, publicDomain);
+        DBGroup privPubGroup = createGroup("privPubGroup", VisibilityType.PUBLIC, privateDomain);
+        DBGroup privPrivGroup = createGroup("privPrivGroup", VisibilityType.PRIVATE, privateDomain);
 
-        //assertNotNull(resourceInternalD1G1RD1.getId());
-        assertNotNull(resourcePrivateD1G1RD1.getId());
+        createGroupMembership(MembershipRoleType.VIEWER, user4, privPrivGroup);
 
+        DBResource pubPubPubRes = createResource("pubPubPub", "1-1-1", VisibilityType.PUBLIC, publicDomainResourceDef,  pubPubGroup);
+        DBResource pubPubPrivRes = createResource("pubPubPriv", "2-2-2", VisibilityType.PRIVATE, publicDomainResourceDef,  pubPubGroup);
+        DBResource pubPrivPubRes = createResource("pubPrivPub", "3-3-3", VisibilityType.PUBLIC, publicDomainResourceDef,  pubPrivGroup);
+        DBResource pubPrivPrivRes = createResource("pubPrivPriv", "4-4-4", VisibilityType.PRIVATE, publicDomainResourceDef,  pubPrivGroup);
 
+        DBResource privPubPubRes = createResource("privPubPub", "5-5-5", VisibilityType.PUBLIC, privateDomainResourceDef,  privPubGroup);
+        DBResource privPubPrivRes = createResource("privPubPriv", "6-6-6", VisibilityType.PRIVATE, privateDomainResourceDef,  privPubGroup);
+        DBResource privPrivPubRes = createResource("privPrivPub", "7-7-7", VisibilityType.PUBLIC, privateDomainResourceDef,  privPrivGroup);
+        DBResource privPrivPrivRes = createResource("privPrivPriv", "8-8-8", VisibilityType.PRIVATE, privateDomainResourceDef,  privPrivGroup);
 
-        DBResourceMember  privateRM_U1R1_D1G1Admin = createResourceMembership(MembershipRoleType.ADMIN, user1, resourcePrivateD1G1RD1);
-        //DBResourceMember  internalRM_U1R1_D1G1Viewer = createResourceMembership(MembershipRoleType.VIEWER, user1, resourceInternalD1G1RD1);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPubPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPubPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPubPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPubPrivRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPrivPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPrivPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPrivPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPrivPrivRes);
 
-        persistFlushDetach(privateRM_U1R1_D1G1Admin);
-       // persistFlushDetach(internalRM_U1R1_D1G1Viewer);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, privPubPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, privPubPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, privPubPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, privPubPrivRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, privPrivPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, privPrivPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, privPrivPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, privPrivPrivRes);
+
+        createResourceMembership(MembershipRoleType.VIEWER, user5, privPrivPrivRes);
+
+        searchDataCreated = true;
     }
 
+    @Transactional
     public DBDomainMember createDomainMembership(MembershipRoleType roleType, DBUser user, DBDomain domain){
         DBDomainMember domainMember = new DBDomainMember();
         domainMember.setRole(roleType);
         domainMember.setUser(user);
         domainMember.setDomain(domain);
+        persistFlushDetach(domainMember);
+        assertNotNull(domainMember.getId());
         return domainMember;
     }
 
+    @Transactional
     public DBGroupMember createGroupMembership(MembershipRoleType roleType, DBUser user, DBGroup group){
         DBGroupMember member = new DBGroupMember();
         member.setRole(roleType);
         member.setUser(user);
         member.setGroup(group);
+        persistFlushDetach(member);
+        assertNotNull(member.getId());
         return member;
     }
 
+    @Transactional
     public DBResourceMember createResourceMembership(MembershipRoleType roleType, DBUser user, DBResource resource){
         DBResourceMember member = new DBResourceMember();
         member.setRole(roleType);
         member.setUser(user);
         member.setResource(resource);
+        persistFlushDetach(member);
+        assertNotNull(member.getId());
         return member;
     }
 
@@ -351,14 +381,16 @@ public class TestUtilsDao {
         documentD1G1RD1 = createDocument(2);
         documentD2G1RD1 = createDocument(2);
         resourceD1G1RD1 = TestDBUtils.createDBResource(TEST_SG_ID_1, TEST_SG_SCHEMA_1);
+        resourceD1G1RD1.setDocument(documentD1G1RD1);
+
         resourceD1G1RD1.setGroup(groupD1G1);
         resourceD1G1RD1.setDomainResourceDef(domainResourceDefD1R1);
-        resourceD1G1RD1.setDocument(documentD1G1RD1);
 
         resourceD2G1RD1 = TestDBUtils.createDBResource(TEST_SG_ID_2, null);
+        resourceD2G1RD1.setDocument(documentD2G1RD1);
+
         resourceD2G1RD1.setGroup(groupD2G1);
         resourceD2G1RD1.setDomainResourceDef(domainResourceDefD2R1);
-        resourceD2G1RD1.setDocument(documentD2G1RD1);
 
         persistFlushDetach(resourceD1G1RD1);
         persistFlushDetach(resourceD2G1RD1);
@@ -367,6 +399,19 @@ public class TestUtilsDao {
         assertNotNull(resourceD2G1RD1.getId());
     }
 
+    @Transactional
+    public DBResource createResource(String identifier, String schema, VisibilityType visibilityType, DBDomainResourceDef domainResourceDef, DBGroup group) {
+
+        DBResource resource = TestDBUtils.createDBResource(identifier, schema);
+        resource.setVisibility(visibilityType);
+        resource.setGroup(group);
+        resource.setDomainResourceDef(domainResourceDef);
+
+        persistFlushDetach(resource);
+        assertNotNull(resource.getId());
+        return resource;
+    }
+
 
     /**
      * Create resources with subresources  for ids:
@@ -458,17 +503,19 @@ public class TestUtilsDao {
             return;
         }
         createDomains();
-        groupD1G1 = TestDBUtils.createDBGroup(TEST_GROUP_A);
-        groupD1G2 = TestDBUtils.createDBGroup(TEST_GROUP_B);
-        groupD2G1 = TestDBUtils.createDBGroup(TEST_GROUP_A);
+        groupD1G1 = createGroup(TEST_GROUP_A, VisibilityType.PUBLIC, d1);
+        groupD1G2 = createGroup(TEST_GROUP_B, VisibilityType.PUBLIC, d1);
+        groupD2G1 = createGroup(TEST_GROUP_A, VisibilityType.PUBLIC, d2);
+    }
 
-        groupD1G1.setDomain(d1);
-        groupD1G2.setDomain(d1);
-        groupD2G1.setDomain(d2);
+    @Transactional
+    public DBGroup createGroup(String groupName, VisibilityType visibility, DBDomain domain){
+        DBGroup group = createDBGroup(groupName, visibility);
+        group.setDomain(domain);
+        persistFlushDetach(group);
+        assertNotNull(group.getId());
 
-        persistFlushDetach(groupD1G1);
-        persistFlushDetach(groupD1G2);
-        persistFlushDetach(groupD2G1);
+        return group;
     }
 
     @Transactional
@@ -480,7 +527,13 @@ public class TestUtilsDao {
 
     @Transactional
     public DBDomain createDomain(String domainCode) {
+     return createDomain(domainCode, VisibilityType.PUBLIC);
+    }
+
+    @Transactional
+    public DBDomain createDomain(String domainCode, VisibilityType visibility) {
         DBDomain d = TestDBUtils.createDBDomain(domainCode);
+        d.setVisibility(visibility);
         persistFlushDetach(d);
         return d;
     }
@@ -563,6 +616,14 @@ public class TestUtilsDao {
         return user3;
     }
 
+    public DBUser getUser4() {
+        return user4;
+    }
+
+    public DBUser getUser5() {
+        return user5;
+    }
+
     public DBGroup getGroupD1G1() {
         return groupD1G1;
     }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java
index 40499de70..7bc0eee99 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java
@@ -47,6 +47,8 @@ public class TestConstants {
     public static final String USERNAME_1 = "test-user_001";
     public static final String USERNAME_2 = "test-user_002";
     public static final String USERNAME_3 = "test-user_003";
+    public static final String USERNAME_4 = "test-user_004";
+    public static final String USERNAME_5 = "test-user_005";
     public static final String USERNAME_TOKEN_1 = TOKEN_PREFIX + USERNAME_1;
     public static final String USERNAME_TOKEN_2 = TOKEN_PREFIX + USERNAME_2;
     public static final String USERNAME_TOKEN_3 = TOKEN_PREFIX + USERNAME_3;
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
index 48317b202..01c91dcd8 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
@@ -38,10 +38,14 @@ public class TestDBUtils {
     }
 
     public static DBGroup createDBGroup(String groupName) {
+        return  createDBGroup(groupName, VisibilityType.PUBLIC);
+    }
+
+    public static DBGroup createDBGroup(String groupName, VisibilityType visibility){
         DBGroup group = new DBGroup();
         group.setGroupName(groupName);
         group.setGroupDescription(anyString());
-        group.setVisibility(VisibilityType.PUBLIC);
+        group.setVisibility(visibility);
         return group;
     }
 
-- 
GitLab