Skip to content

Conversation

igdianov
Copy link
Collaborator

@igdianov igdianov commented Jun 21, 2020

This PR adds support for row filtering via restricting query search criteria using pluggable RestrictedKeysProvider implementation.

The RestrictedKeysProvider functional interface should provide a list of restricted keys in order to filter records at runtime based on user security context and supplied EntityIntrospection descriptor arugment.

The return argument uses Optional<List> return type.

  • The non-empty list will restrict the query results to provided keys
  • The empty list will execute the query without any restrictions.
  • The empty Optional will block running the query and return empty result list or null value.
@FunctionalInterface
public interface RestrictedKeysProvider extends Function<EntityIntrospectionResult, Optional<List<Object>>> {

    /**
     * Applies this restricted keys provider function to the given argument of entityDescriptor.
     *
     * @param entityDescriptor the function argument
     * @return the function result with optional list of keys
     */
    @Override
    Optional<List<Object>> apply(EntityIntrospectionResult entityDescriptor);
    
}

You can configure the implementation of the provider via GraphqJpaSchemaBuilder.restrictedKeysProvider builder method Java Api, i.e.,

graphQLSchemaBuilder = GraphQLJpaSchemaBuilder(entityManager)
                .name("GraphQLBooks")
                .description("Books JPA test schema")
                .restrictedKeysProvider(new SpringSecurityRestrictedKeysProvider(entityManager.getMetamode()));
public class SpringSecurityRestrictedKeysProvider implements RestrictedKeysProvider {
    
    private final Metamodel metamodel;
    
    public SpringSecurityRestrictedKeysProvider(Metamodel metamodel) {
        this.metamodel = metamodel;
    }

    @Override
    public Optional<List<Object>> apply(EntityIntrospectionResult entityDescriptor) {
        Authentication token = SecurityContextHolder.getContext()
                                                    .getAuthentication();
        if (token == null) {
            return Optional.empty();
        }
        
        // resolve entity name from descriptor
        String entityName = metamodel.entity(entityDescriptor.getEntity())
                                     .getName();

        // resolve keys from entityName and user token in permission store
        List<Object> keys = resolveKeys(entityName, token);

        return keys.isEmpty() ? Optional.empty() // restrict query if no permissions exists 
                              : Optional.of(keys); // execute query with restricted keys
    }
    

The provided graphql-jpa-query-boot-starter will detect and automatically inject RestrictedKeysProvider bean instance from application context.

Fixes #219

@igdianov igdianov self-assigned this Jun 21, 2020
@codecov
Copy link

codecov bot commented Jun 21, 2020

Codecov Report

Merging #274 into master will increase coverage by 2.38%.
The diff coverage is 89.87%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #274      +/-   ##
============================================
+ Coverage     72.14%   74.53%   +2.38%     
- Complexity     1031     1083      +52     
============================================
  Files            72       72              
  Lines          4696     4751      +55     
  Branches        672      679       +7     
============================================
+ Hits           3388     3541     +153     
+ Misses         1019      919     -100     
- Partials        289      291       +2     
Impacted Files Coverage Δ Complexity Δ
...query/schema/relay/GraphQLJpaRelayDataFetcher.java 93.75% <81.81%> (+93.75%) 6.00 <0.00> (+6.00)
...jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java 90.76% <88.88%> (+2.05%) 141.00 <2.00> (+12.00)
.../jpa/query/schema/impl/GraphQLJpaQueryFactory.java 78.91% <89.13%> (+0.54%) 229.00 <7.00> (+9.00)
...utoconfigure/GraphQLJpaQueryAutoConfiguration.java 100.00% <100.00%> (ø) 1.00 <0.00> (ø)
.../query/schema/impl/GraphQLJpaQueryDataFetcher.java 93.18% <100.00%> (+3.18%) 9.00 <0.00> (+2.00)
...phql/jpa/query/schema/impl/EntityIntrospector.java 71.22% <0.00%> (+0.71%) 8.00% <0.00%> (ø%)
...res/graphql/jpa/query/schema/impl/PagedResult.java 88.88% <0.00%> (+3.70%) 6.00% <0.00%> (+1.00%)
.../graphql/jpa/query/introspection/Constructors.java 82.00% <0.00%> (+4.00%) 15.00% <0.00%> (+1.00%)
...query/schema/impl/GraphQLJpaSimpleDataFetcher.java 100.00% <0.00%> (+7.69%) 5.00% <0.00%> (ø%)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dae311b...c9cfac7. Read the comment docs.

@igdianov igdianov merged commit 37f1416 into master Jun 22, 2020
@igdianov igdianov deleted the feat-restricted-keys-provider branch June 22, 2020 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Row-level filtering
1 participant