Skip to content

Commit 88e0f14

Browse files
committed
feat: wip
1 parent 9a1f97d commit 88e0f14

9 files changed

Lines changed: 85 additions & 21 deletions

File tree

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,13 @@
482482
<version>${geojson-jackson.version}</version>
483483
</dependency>
484484

485+
<!-- JsonPath -->
486+
<dependency>
487+
<groupId>com.jayway.jsonpath</groupId>
488+
<artifactId>json-path</artifactId>
489+
<version>2.8.0</version>
490+
</dependency>
491+
485492
<!-- Keycloak -->
486493
<dependency>
487494
<groupId>org.keycloak</groupId>

shogun-lib/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@
212212
<artifactId>tika-core</artifactId>
213213
</dependency>
214214

215+
<dependency>
216+
<groupId>com.jayway.jsonpath</groupId>
217+
<artifactId>json-path</artifactId>
218+
</dependency>
219+
215220
<!-- Testing -->
216221
<dependency>
217222
<groupId>org.springframework</groupId>

shogun-lib/src/main/java/de/terrestris/shogun/lib/controller/BaseController.java

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,23 @@
1717
package de.terrestris.shogun.lib.controller;
1818

1919
import com.github.fge.jsonpatch.mergepatch.JsonMergePatch;
20+
import com.jayway.jsonpath.Criteria;
21+
import com.jayway.jsonpath.Filter;
22+
import com.jayway.jsonpath.JsonPath;
23+
import com.jayway.jsonpath.internal.Path;
24+
import com.jayway.jsonpath.internal.filter.FilterCompiler;
25+
import com.jayway.jsonpath.internal.path.PathCompiler;
2026
import de.terrestris.shogun.lib.controller.security.permission.BasePermissionController;
2127
import de.terrestris.shogun.lib.model.BaseEntity;
22-
import de.terrestris.shogun.lib.model.User;
2328
import de.terrestris.shogun.lib.service.BaseService;
2429
import io.swagger.v3.oas.annotations.Operation;
2530
import io.swagger.v3.oas.annotations.Parameter;
2631
import io.swagger.v3.oas.annotations.media.Content;
27-
import io.swagger.v3.oas.annotations.media.Schema;
2832
import io.swagger.v3.oas.annotations.responses.ApiResponse;
2933
import io.swagger.v3.oas.annotations.responses.ApiResponses;
3034
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
3135
import lombok.extern.log4j.Log4j2;
36+
import org.apache.commons.lang3.StringUtils;
3237
import org.springdoc.api.annotations.ParameterObject;
3338
import org.springframework.beans.factory.annotation.Autowired;
3439
import org.springframework.context.MessageSource;
@@ -45,9 +50,7 @@
4550
import org.springframework.web.bind.annotation.*;
4651
import org.springframework.web.server.ResponseStatusException;
4752

48-
import java.lang.reflect.ParameterizedType;
4953
import java.time.OffsetDateTime;
50-
import java.util.List;
5154
import java.util.Optional;
5255

5356
// TODO Specify and type extension of BaseService
@@ -78,26 +81,47 @@ public abstract class BaseController<T extends BaseService<?, S>, S extends Base
7881
description = "Unauthorized: You need to provide a bearer token",
7982
content = @Content
8083
),
81-
@ApiResponse(
82-
responseCode = "404",
83-
description = "Not found: The provided ID does not exist (or you don't have the permission to delete it)"
84-
),
84+
// @ApiResponse(
85+
// responseCode = "404",
86+
// description = "Not found: The provided ID does not exist (or you don't have the permission to delete it)"
87+
// ),
8588
@ApiResponse(
8689
responseCode = "500",
87-
description = "Internal Server Error: Something internal went wrong while deleting the entity"
90+
description = "Internal Server Error: Something internal went wrong while getting the entity list"
8891
)
8992
})
90-
public Page<S> findAll(@PageableDefault(Integer.MAX_VALUE) @ParameterObject Pageable pageable) {
93+
// TODO Custom annotation to get filterobject directly, similiar to @ParameterObect
94+
public Page<S> findAll(@PageableDefault(Integer.MAX_VALUE) @ParameterObject Pageable pageable, @RequestParam(required = false) String filter) {
9195
log.trace("Requested to return all entities of type {}", getGenericClassName());
9296

97+
// Path compiledPath = PathCompiler.compile("$.phoneNumbers[?(@.type=='home')]");
98+
//
99+
// Filter parsedFilter = Filter.parse("$.phoneNumbers[?(@.type=='home')]");
100+
//
101+
// Filter compiled = FilterCompiler.compile("$.phoneNumbers[?(@.type=='home')]");
102+
// new FilterCompiler("$.phoneNumbers[?(@.type=='home')]");
103+
//
104+
// Criteria crit = Criteria.parse("$.phoneNumbers[?(@.type=='home')]");
105+
93106
try {
94-
Page<S> persistedEntities = service.findAll(pageable);
107+
// https://github.com/json-path/JsonPath
108+
if (StringUtils.isNotEmpty(filter)) {
109+
// TODO Parse and validate filter
110+
//JsonPath peter = JsonPath.compile("$.phoneNumbers[?(@.type=='home')]");
111+
JsonPath compiledFilter = JsonPath.compile(filter);
112+
// Filter compiledFilter = Filter.parse(filter);
113+
114+
log.trace("Got filter " + compiledFilter.toString());
115+
}
116+
117+
Page<S> persistedEntities = service.findAll(pageable, filter);
95118

96119
log.trace("Successfully got all entities of type {} (count: {})",
97120
getGenericClassName(), persistedEntities.getTotalElements());
98121

99122
return persistedEntities;
100123
} catch (AccessDeniedException ade) {
124+
// TODO I don't think we'll ever get into this exception here
101125
log.warn("Access to entity of type {} is denied", getGenericClassName());
102126

103127
throw new ResponseStatusException(

shogun-lib/src/main/java/de/terrestris/shogun/lib/repository/BaseCrudRepository.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,27 @@ AND gip.permission.name IN ('ADMIN', 'READ', 'CREATE_READ', 'CREATE_READ_UPDATE'
9191
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
9292
Page<T> findAll(Pageable pageable);
9393

94+
@Query(
95+
value = """
96+
SELECT
97+
e.*
98+
FROM
99+
#{#entityName} e
100+
WHERE
101+
:filter IS NULL OR CAST(row_to_json(e) AS JSONB) @@ CAST(:filter AS JSONPATH)
102+
""",
103+
countQuery = """
104+
SELECT
105+
COUNT(e.*)
106+
FROM
107+
#{#entityName} e
108+
""",
109+
nativeQuery = true
110+
)
111+
@QueryHints(
112+
value = @QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"),
113+
forCounting = false
114+
)
115+
Page<T> findAll(Pageable pageable, String filter);
116+
94117
}

shogun-lib/src/main/java/de/terrestris/shogun/lib/security/access/entity/BaseEntityPermissionEvaluator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public boolean hasPermissionByGroupClassPermission(User user, BaseEntity entity,
258258
* @return A page of entities.
259259
*/
260260
@Override
261-
public Page<E> findAll(User user, Pageable pageable, BaseCrudRepository<E, Long> repository, Class<E> baseEntityClass) {
261+
public Page<E> findAll(User user, Pageable pageable, String filter, BaseCrudRepository<E, Long> repository, Class<E> baseEntityClass) {
262262
if (user == null) {
263263
throw new RuntimeException("No user provided!");
264264
}
@@ -272,15 +272,15 @@ public Page<E> findAll(User user, Pageable pageable, BaseCrudRepository<E, Long>
272272
);
273273

274274
if (isAdmin) {
275-
return repository.findAll(pageable);
275+
return repository.findAll(pageable, filter);
276276
}
277277

278278
// option B: user has permission through class permissions
279279
Optional<UserClassPermission> userClassPermission = userClassPermissionService.findFor(baseEntityClass, user);
280280
Optional<GroupClassPermission> groupClassPermission = groupClassPermissionService.findFor(baseEntityClass, user);
281281

282282
if (containsReadPermission(userClassPermission.orElse(null), groupClassPermission.orElse(null))) {
283-
return repository.findAll(pageable);
283+
return repository.findAll(pageable, filter);
284284
}
285285

286286
// option C: check instance permissions for each entity with a single query

shogun-lib/src/main/java/de/terrestris/shogun/lib/security/access/entity/EntityPermissionEvaluator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ public interface EntityPermissionEvaluator<E> {
3737
* with pagination. See {@link BaseEntityPermissionEvaluator#findAll(User, Pageable, BaseCrudRepository)} for the
3838
* default implementation for {@link de.terrestris.shogun.lib.model.BaseEntity}.
3939
*/
40-
Page<E> findAll(User user, Pageable pageable, BaseCrudRepository<E, Long> repository, Class<E> baseEntityClass);
40+
Page<E> findAll(User user, Pageable pageable, String filter, BaseCrudRepository<E, Long> repository, Class<E> baseEntityClass);
4141
}

shogun-lib/src/main/java/de/terrestris/shogun/lib/security/access/entity/GroupPermissionEvaluator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public class GroupPermissionEvaluator extends BaseEntityPermissionEvaluator<Grou
3232
GroupProviderService groupProviderService;
3333

3434
@Override
35-
public Page<Group> findAll(User user, Pageable pageable, BaseCrudRepository<Group, Long> repository,
35+
public Page<Group> findAll(User user, Pageable pageable, String filter, BaseCrudRepository<Group, Long> repository,
3636
Class<Group> baseEntityClass) {
37-
Page<Group> groups = super.findAll(user, pageable, repository, baseEntityClass);
37+
Page<Group> groups = super.findAll(user, pageable, filter, repository, baseEntityClass);
3838

3939
groups.forEach(u -> groupProviderService.setTransientRepresentations(u));
4040

shogun-lib/src/main/java/de/terrestris/shogun/lib/security/access/entity/UserPermissionEvaluator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public class UserPermissionEvaluator extends BaseEntityPermissionEvaluator<User>
3131
UserProviderService userProviderService;
3232

3333
@Override
34-
public Page<User> findAll(User user, Pageable pageable, BaseCrudRepository<User, Long> repository,
34+
public Page<User> findAll(User user, Pageable pageable, String filter, BaseCrudRepository<User, Long> repository,
3535
Class<User> baseEntityClass) {
36-
Page<User> users = super.findAll(user, pageable, repository, baseEntityClass);
36+
Page<User> users = super.findAll(user, pageable, filter, repository, baseEntityClass);
3737

3838
users.forEach(u -> userProviderService.setTransientRepresentations(u));
3939

shogun-lib/src/main/java/de/terrestris/shogun/lib/service/BaseService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public List<S> findAll() {
8989
}
9090

9191
@Transactional(readOnly = true)
92-
public Page<S> findAll(Pageable pageable) {
92+
public Page<S> findAll(Pageable pageable, String filter) {
9393
// note: security check is done in permission evaluator
9494
Optional<User> userOpt = userProviderService.getUserBySession();
9595

@@ -99,7 +99,12 @@ public Page<S> findAll(Pageable pageable) {
9999
BaseEntityPermissionEvaluator entityPermissionEvaluator =
100100
this.getPermissionEvaluatorForClass(entityClass.getCanonicalName());
101101

102-
return entityPermissionEvaluator.findAll(userOpt.orElse(null), pageable, repository, entityClass);
102+
return entityPermissionEvaluator.findAll(userOpt.orElse(null), pageable, filter, repository, entityClass);
103+
}
104+
105+
@Transactional(readOnly = true)
106+
public Page<S> findAll(Pageable pageable) {
107+
return this.findAll(pageable, null);
103108
}
104109

105110
@PostFilter("hasRole('ROLE_ADMIN') or hasPermission(filterObject, 'READ')")

0 commit comments

Comments
 (0)