Repository: kestra-io/kestra
Issue: Filter on namespace
Labels: bug

### Expected Behavior

When we filter on a namepace we must only see the selected namespace.
Ex: If I have 2 namespace com.test and com.test2
If I select com.test, the 2 namespaces will be displayed. 

### Actual Behaviour

_No response_

### Steps To Reproduce

_No response_

### Environment Information

- Kestra Version: 0.8
- Operating System (OS / Docker / Kubernetes):
- Java Version (If not docker):


### Example flow

_No response_

Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcExecutionRepository.java b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcExecutionRepository.java
index 181cf5dca5..2f6160076a 100644
--- a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcExecutionRepository.java
+++ b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcExecutionRepository.java
@@ -340,7 +340,7 @@ private <T extends Record> SelectConditionStep<T> filteringQuery(
             select = select.and(field("namespace").eq(namespace));
             select = select.and(field("flow_id").eq(flowId));
         } else if (namespace != null) {
-            select = select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+            select = select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
         }
 
         if (query != null) {
diff --git a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcFlowRepository.java b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcFlowRepository.java
index 1613cc730e..e15ea66112 100644
--- a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcFlowRepository.java
+++ b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcFlowRepository.java
@@ -232,7 +232,7 @@ public ArrayListTotal<Flow> find(
                 select.and(this.findCondition(query, labels));
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 return this.jdbcRepository.fetchPage(context, select, pageable);
@@ -255,7 +255,7 @@ public List<FlowWithSource> findWithSource(
                 select.and(this.findCondition(query, labels));
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 return select.fetch().map(record -> FlowWithSource.of(
@@ -282,7 +282,7 @@ public ArrayListTotal<SearchResult<Flow>> findSourceCode(Pageable pageable, @Nul
                 }
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 return this.jdbcRepository.fetchPage(
diff --git a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcLogRepository.java b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcLogRepository.java
index c31f63d524..c5c0ba2149 100644
--- a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcLogRepository.java
+++ b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcLogRepository.java
@@ -47,7 +47,7 @@ public ArrayListTotal<LogEntry> find(
                     .where(this.defaultFilter());
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 if (flowId != null) {
diff --git a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcTemplateRepository.java b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcTemplateRepository.java
index 7ebf923b5f..e7f51c2272 100644
--- a/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcTemplateRepository.java
+++ b/jdbc/src/main/java/io/kestra/jdbc/repository/AbstractJdbcTemplateRepository.java
@@ -90,7 +90,7 @@ public ArrayListTotal<Template> find(
                 }
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 return this.jdbcRepository.fetchPage(context, select, pageable);
@@ -117,7 +117,7 @@ public List<Template> find(@Nullable String query, @Nullable String namespace) {
                 }
 
                 if (namespace != null) {
-                    select.and(field("namespace").likeIgnoreCase(namespace + "%"));
+                    select.and(DSL.or(field("namespace").eq(namespace), field("namespace").likeIgnoreCase(namespace + ".%")));
                 }
 
                 return this.jdbcRepository.fetch(select);
diff --git a/repository-memory/src/main/java/io/kestra/repository/memory/MemoryFlowRepository.java b/repository-memory/src/main/java/io/kestra/repository/memory/MemoryFlowRepository.java
index 5f3db19442..143eaf4905 100644
--- a/repository-memory/src/main/java/io/kestra/repository/memory/MemoryFlowRepository.java
+++ b/repository-memory/src/main/java/io/kestra/repository/memory/MemoryFlowRepository.java
@@ -131,7 +131,7 @@ public ArrayListTotal<Flow> find(
         //TODO Non used query, just returns all flow and filter by namespace if set
         List<Flow> results = flows.values()
             .stream()
-            .filter(flow -> namespace == null || flow.getNamespace().startsWith(namespace))
+            .filter(flow -> namespace == null || flow.getNamespace().equals(namespace) || flow.getNamespace().startsWith(namespace + "."))
             .collect(Collectors.toList());
         return ArrayListTotal.of(pageable, results);
     }
@@ -145,7 +145,7 @@ public List<FlowWithSource> findWithSource(
         //TODO Non used query, just returns all flow and filter by namespace if set
         return flows.values()
             .stream()
-            .filter(flow -> namespace == null || flow.getNamespace().startsWith(namespace))
+            .filter(flow ->  namespace == null || flow.getNamespace().equals(namespace) || flow.getNamespace().startsWith(namespace + "."))
             .sorted(Comparator.comparingInt(Flow::getRevision))
             .map(flow -> findByIdWithSource(flow.getNamespace(), flow.getId(), Optional.of(flow.getRevision())).get())
             .collect(Collectors.toList());


Test patch:
diff --git a/core/src/test/java/io/kestra/core/Helpers.java b/core/src/test/java/io/kestra/core/Helpers.java
index 82bd964bb3..9c297da7a8 100644
--- a/core/src/test/java/io/kestra/core/Helpers.java
+++ b/core/src/test/java/io/kestra/core/Helpers.java
@@ -19,7 +19,7 @@
 import java.util.function.Consumer;
 
 public class Helpers {
-    public static long FLOWS_COUNT = 63;
+    public static long FLOWS_COUNT = 64;
 
     public static ApplicationContext applicationContext() throws URISyntaxException {
         return applicationContext(
diff --git a/core/src/test/java/io/kestra/core/repositories/AbstractFlowRepositoryTest.java b/core/src/test/java/io/kestra/core/repositories/AbstractFlowRepositoryTest.java
index 7640ee857d..eaae927074 100644
--- a/core/src/test/java/io/kestra/core/repositories/AbstractFlowRepositoryTest.java
+++ b/core/src/test/java/io/kestra/core/repositories/AbstractFlowRepositoryTest.java
@@ -212,7 +212,10 @@ void findAll() {
     @Test
     void findByNamespace() {
         List<Flow> save = flowRepository.findByNamespace("io.kestra.tests");
-        assertThat((long) save.size(), is(Helpers.FLOWS_COUNT - 1));
+        assertThat((long) save.size(), is(Helpers.FLOWS_COUNT - 2));
+
+        save = flowRepository.findByNamespace("io.kestra.tests2");
+        assertThat((long) save.size(), is(1L));
 
         save = flowRepository.findByNamespace("io.kestra.tests.minimal.bis");
         assertThat((long) save.size(), is(1L));
@@ -230,7 +233,10 @@ void find() {
     @Test
     void findWithSource() {
         List<FlowWithSource> save = flowRepository.findWithSource(null, "io.kestra.tests", Collections.emptyMap());
-        assertThat((long) save.size(), is(Helpers.FLOWS_COUNT));
+        assertThat((long) save.size(), is(Helpers.FLOWS_COUNT - 1));
+
+        save = flowRepository.findWithSource(null, "io.kestra.tests2", Collections.emptyMap());
+        assertThat((long) save.size(), is(1L));
 
         save = flowRepository.findWithSource(null, "io.kestra.tests.minimal.bis", Collections.emptyMap());
         assertThat((long) save.size(), is(1L));
@@ -368,7 +374,7 @@ void removeTriggerDelete() throws InterruptedException {
     @Test
     void findDistinctNamespace() {
         List<String> distinctNamespace = flowRepository.findDistinctNamespace();
-        assertThat((long) distinctNamespace.size(), is(2L));
+        assertThat((long) distinctNamespace.size(), is(3L));
     }
 
     @Singleton
diff --git a/core/src/test/resources/flows/valids/minimal2.yaml b/core/src/test/resources/flows/valids/minimal2.yaml
new file mode 100644
index 0000000000..1689ef77e0
--- /dev/null
+++ b/core/src/test/resources/flows/valids/minimal2.yaml
@@ -0,0 +1,7 @@
+id: minimal
+namespace: io.kestra.tests2
+
+tasks:
+- id: date
+  type: io.kestra.core.tasks.debugs.Return
+  format: "{{taskrun.startDate}}"
diff --git a/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java b/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
index 9bbd8b9493..946c96339d 100644
--- a/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
+++ b/webserver/src/test/java/io/kestra/webserver/controllers/FlowControllerTest.java
@@ -393,7 +393,7 @@ void listDistinctNamespace() {
         List<String> namespaces = client.toBlocking().retrieve(
             HttpRequest.GET("/api/v1/flows/distinct-namespaces"), Argument.listOf(String.class));
 
-        assertThat(namespaces.size(), is(2));
+        assertThat(namespaces.size(), is(3));
     }
 
     @Test
@@ -496,7 +496,7 @@ void exportByQuery() throws IOException {
         Files.write(file.toPath(), zip);
 
         try (ZipFile zipFile = new ZipFile(file)) {
-            assertThat(zipFile.stream().count(), is(Helpers.FLOWS_COUNT));
+            assertThat(zipFile.stream().count(), is(Helpers.FLOWS_COUNT -1));
         }
 
         file.delete();