How can we improve Breeze.js?

QueryInterceptors and ChangeInterceptor are needed to implement Security

One needs to write lots of code to implement query and change interception to EF context. With interceptors we can easily do this with Breeze like WCF Data Services.

35 votes
Vote
Sign in
(thinking…)
Sign in with: facebook google
Signed in as (Sign out)
You have left! (?) (thinking…)
Umut shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

14 comments

Sign in
(thinking…)
Sign in with: facebook google
Signed in as (Sign out)
Submitting...
  • odeyinka olubunmi commented  ·   ·  Flag as inappropriate

    @Ward and @Jonny the only way round this is to call the service that will return the data as json from a C# code using httpWebClient or httpWebRequest downloading the json result. DeSerializing it with JsonConvert.DeserializeObject etc.back to C# objects and use the object for your reports.
    I just wrote a class that u pass the endpoint to and does all this and is working for me

  • Ward Bell commented  ·   ·  Flag as inappropriate

    Not to my knowledge. The execution of the LINQ query occurs outside the controller method. There is no way to inspect the results.

    The only way I know to intercept the results is to execute the query yourself after applying the client's query specification ... which is no easy task.

    .. or to write a custom Web API filter (for example, modify the JSON serialization filter with a custom Json.Net serialization interceptor) ... which seem like the wrong abstractions to me and would be no easy task either.

    I've been thinking about an option on the BreezeEnableQuery attribute for calling back into some method in your controller that could post-process the results before sending them out of the controller, toward the client (that is, onward to the filters). I have gotten no further than speculation.

  • Ward Bell commented  ·   ·  Flag as inappropriate

    You can get the query string from the URL programmatically with code like this:

    var allUrlKeyValues = ControllerContext.Request.GetQueryNameValuePairs();
    string filter = allUrlKeyValues.SingleOrDefault(x => x.Key == "$filter").Value;

    What you do with it is another matter.

  • Jonny Nguyen commented  ·   ·  Flag as inappropriate

    Is it possible to get the filter data on the server side using some kind of intercept. The main idea is for exporting the data to csv. This should allow you to use the same query for your export.

  • bap commented  ·   ·  Flag as inappropriate

    Ward, I just did a file/new project with the Breeze/Knockout template and confirmed the iQueryable filter stays on the server. This is great news! For some reason i thought the flter portion of the iQueryable was also returned to the client. Thanks for your patience and clarification. I'm drinking the breeze koolaid. :)

  • Ward Bell commented  ·   ·  Flag as inappropriate

    @bap Just to be extra clear: the controller METHOD returns IQueryable but what goes to the client is JSON DATA ... the result of server-side execution of the IQueryable. The IQueryable itself never leaves the server.

  • Ward Bell commented  ·   ·  Flag as inappropriate

    @bap You made the argument against including the UserID in the query from the client. it is useless from a security perspective. So don't bother. No, whatever extra filtering you do on the server stays on the server. It is not communicated to the client. There is nothing to spoof. The client's filter criteria are ANDed with the server's so the client can't expand the query. Now it doesn't hurt (belt-and-suspenders) if you want to see if the client tried to mention UserId. You can actually do that pretty easily simply by applying a RegEx to the request text ... which you have access to within any Web API controller method. But I'm not that paranoid :)

  • bap commented  ·   ·  Flag as inappropriate

    thanks for the quick response Ward. yep, we can get to the user context from iPrincipal on the server. but if we return an iqueryable that includes userID in where statement such as "datacontext.appointments.where(a => a.userID = "joe") would breeze include the userID in the odata filter expression on the client in subsequent calls? if so, wouldn't it be easy to spoof the userID on the client? If there is a query interceptor we could always check the filter in the query expression to ensure userID="joe" prior to executing query. maybe i'm getting ahead of myself...i'm very new to breeze...thanks.

  • Ward Bell commented  ·   ·  Flag as inappropriate

    The logged in user is available to you on the server now. It should be in your identity that is in the `IPrincipal` (`System.Threading.Thread.CurrentPrincipal`). If you didn't put the `UserId` in the identity during your authentication step (which I recommend), you should be able to use that identity to acquire the `UserID`. The ASP.NET SPA Template and both Breeze SPA Templates illustrate this technique (they use the Web API controller's `User` property which is just a wrapper around `CurrentPrincipal`); all of them filter the TodoLists by `UserId`. So I don't think there is an action item for Breeze.

  • bap commented  ·   ·  Flag as inappropriate

    We have a multi-tennant application that needs to partition every query by customerID. We would like to get the customerID from the logged-in userID using forms authentication on the server then append the customerID=id filter to every query to be executed. We need to handle this on the server for security purposes. Does that make sense?

  • Umut commented  ·   ·  Flag as inappropriate

    I see your point -in fact at first we created a custom action filter, later we sub-classed EFContextProvider but we removed all and did all work at EF Context level.
    But Action Filter is an attribute so we cannot inject dependencies and we don't want to use static DI Container to get dependencies (at least not at library level).
    If we create custom action filter the code would not be reusable, if we create custom EFContextProvider we strictly couple our code to breeze.
    I want to be able to inject a request/response tracker object to api controller, and trigger it when necessary (interceptions). But most important thing for me is if we have interceptors code would be cleaner, readable, maintainable (and 1337 :))

    At least, you might consider adding some clear events to EFContextProvider (like entity queried, entity added, entity read etc.).
    And lastly, you are right, we can live without this, but one day if nothing is left to add to breeze you can do this :)

  • Anonymous commented  ·   ·  Flag as inappropriate

    I think Query interceptor can be used for both To read in the incoming Request, perform some authorization(modify the Query to remove Expand clause if user is not authorized), Log the incoming Query. all this happens before Query is Executed againts Database. Once the Query is Executed you can pass the Custom Structure filled with Data. So Query Interceptors are Great Place to perform additional work. You are right OdataActionFilter may be used for that.
    Yes agree before save may be good place for ChangeIntercept

  • Ward Bell commented  ·   ·  Flag as inappropriate

    I understand the interest in QueryInterceptor. What is a ChangeInterceptor? Isn't that covered in the BeforeSave... methods described in http://www.breezejs.com/documentation/server-side-interception ?

    The QueryInterceptor is an interesting challenge. You can write one today by taking over the ODataActionFilter ... that's a natural interception point. Once you were in the pipeline, what would you like to do? Examine the query string (easy). Examine the retrieved entities, including the ones tucked in by $expand (harder and potentially non-performant). Tell us what kinds of things you would do in your interceptor.

Feedback and Knowledge Base