.net-coregraphqlhotchocolate

GraphQL-NetCore. Override params in where clause


I am trying to override parameters passed in where clause which is then used to build the expression tree.

In our response to client property userId is encrypted and passed as encryptedUserId, in all objects where this property is present.

{
  "data": {
    "allEmployees": {
        "totalCount": 51,
        "items": [
            {
                "firstName": "Kristi",
                "encryptedUserId": "8f9279f2c81f22d4a088909c5035dd0f"
            },
            {
                "firstName": "Samantha",
                "encryptedUserId": "df194ab35837a323"
            },
            {
                "firstName": "Ernesto",
                "encryptedUserId": "8927b824450aaad73222166c1e34cb5b"
            }
        ]
    }
  }
}

The issue we are facing comes to queries where client wants to filtrate data based on this userId. So lets assume we want to filtrate the above list by encryptedUserId, here is what the client normally will do:

query{
  allEmployees (
    where: {
        encryptedUserId: {
            eq: "8f9279f2c81f22d4a088909c5035dd0f"
        }
    }
  ){
    totalCount
    items{
        firstName
        encryptedUserId
    }
  }
}

As we are using IQueryable it's getting translated straight to .Where(_s0 => _s0.EncryptedUserId == __p_1), how we can intercept this and override the build expression and create a valid expression for sql?

var decryptedUserId = Decrypt(request.EncryptedUserId);
expression.Where(_s0 => decryptedUserId == __p_1)

Solution

  • For anyone who could might need an solution, posting my workaround.

    I ended up extending the Hot Chocolate IHttpRequestInterceptor, checking if the incoming query contains filtering by encryptedUserId and overriding the query.

    public override ValueTask OnCreateAsync(HttpContext context,
        IRequestExecutor requestExecutor, IQueryRequestBuilder requestBuilder,
        CancellationToken cancellationToken)
    {
        var query = requestBuilder.Create();
        var queryString = query.Query!.ToString();
    
        if (!queryString.Contains(WhereKey) || !queryString.Contains(EncryptedUserIdKey))
            return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken);
    
        var builder = QueryBuilder(queryString, query.VariableValues);
    
        requestBuilder.SetQuery(builder.query);
        requestBuilder.SetVariableValues(builder.variables);
    
        return base.OnCreateAsync(context, requestExecutor, requestBuilder,
            cancellationToken);
    }