Altering breeze query string in the controller before being processed - filter

Scenario: my app runs queries where the user id is used in many cases to filter what data the user can see. The user id is an integer. I don't want the user to be able to simply alter the query string and change the user ID parm to another # (and essentially assume another user's identity). Through our authentication process, each request to the server includes a security token in the header, which was returned to the client when they logged in. During the auth process, this token is stored on the server and is mapped to the user's user id.
What I would like to do is pull the token out of the header, do a lookup and get the user ID that is mapped to the token value (got that working), and then alter the query string to add the user ID.
So a request may come in as
http://localhost/api/app/customerlist
And after I get the user id, it may look like this
http://localhost/api/app/customerlist?$filter=userid%20eq%1234
And then continue on.
This is a simple scenario but illustrates my goal. I am not able to add surrogate keys to the database and use a GUID or some other value as my filter column. Pretty much stuck with the structure.
Thanks

On the server side you can add any filters directly to whatever IQueryable is returned. If you use the Authorize attribute you can also access the user data via the "User" variable.
[BreezeController]
[Authorize]
public class NorthwindIBModelController : ApiController {
[HttpGet]
public IQueryable<Customer> CustomerList() {
var userName = User.Identity.Name;
var filter = filter on customers;
var custs = ContextProvider.Context.Customers.Where({ some filter using userName});
}
}
Also see:
Passing username to Web Api methods in ASP.NET MVC 4

Take a look at the EntityQuery.withParameters method. With it from the client you can take any query and add your user id filter to it. Something like
myQuery = myQuery.withParameters( { userId: 1234});
myEntityManager.executeQuery(myQuery).then(...);
Or am I missing something.

Related

How to inject a value via middleware into a graphql query body (prisma-typegraphql)?

I am currently using prisma-typegraphql for generating a schema and it's props.
Problem:
Is there a way to write a middleware that accesses a value from an arbitrary source, then injects that into the graphql-query arguments? It should be passed to the resolver in a way that makes it seem like the data has been in the query from the start and no modification to the resolver is necessary.
More info
Let's say I have three models, one is Client, one is Project and one is User. The Project has a relationship to the client via its id, identifying the client the project belongs to, same for the user
model Client{
id
name
etc...
}
model User{
id
name
clientId / client
etc...
}
model Project{
id
title
clientId / client
etc...
}
I don't want the clientId from the frontend via query, instead I intend to verify the user making the request and then get the clientId from that user.
Currently my Auth Middleware does verify the user and then passes the user object along in the context. However, due to the generated nature of typegraphql-prisma resolvers, I cannot use the context to inject the data into the resolver without extending every single resolver.
I'd much rather inject the value I want into the graphql query before it reaches the resolver, so the resolver has no idea something changed and processes the query as intended.

Is there any way that hasura decodes the token and can use its content in a query?

I was wondering if there is any way to do this in hasura without resorting to creating another service.
Let me explain, in an api a user sends his token, this is decoded in the backend and and so we know who the user is, this is useful for example to search and return records in the database that only belong to this user.
Is there any way to do that with Hasura? the only return the records that belong to a certain user using its token?.
Token data is available as session data so you can use hasura column presets to insert the user id and add permission to only fetch rows that have user id equal to user id from session https://hasura.io/docs/latest/graphql/core/databases/postgres/schema/default-values/column-presets.html#column-presets

Laravel Client Switching Functionality

I am new to laravel and do not have much experience with using ORM. I am building a system in which I need build functionality to allow user to switch clients with another user. I am not sure what is the best method to achieve this.
Currently client belongs to user, do I need another association for client and user model using different foreign key ?
public function clients()
{
return $this->hasMany('App\Client');
}
public function user()
{
return $this->belongsTo('App\User');
}
Even though a client can only have one user switch request I would like to track all the requests so for example if user A makes request to switch client Test with user B and then make another request to switch the same client with user C I would like to soft delete the first record and create new record for new request. Once the other user accepts the request we change the primary key for client Test in the clients table. Will this be a One To Many / Many To Many relationship ?
What table naming conventions do I need to follow ? Any help will be much appreciated.
If I understand you correctly, you would like to temporarily switch clients for one user to another. What you should do is have another table say switched-clients that holds records for the switches with columns user1 and user2. When you want to retrieve clients, your controller checks this table first and if the record exists where('user1', 'user A') (according to your example), then you retrieve the clients for user2.

Parse - avoid sharing information in specific column of a class

I've got a question about the best way to allow user's information to be visible between users in certain situations.
I have certain columns in User class which are private to the user.
In some activity i'm pointing to user object as 'postedBy' or something else,In this case the entire data regarding user is getting shared.
My question is how to restrict user to get some columns in User class??
usually if you want to restrict an access in parse it should be done via ACL. In ACL you can create role for users who can read/write to the class.
ACL are executed on a class level and not on a column level. In order to expose part of the fields i think you have 2 options:
Create one to one realtionship from your User class to another Class. the second class will contain all columns that not all users can see and for this class create ACL's with the users/roles that can view this data and when you will execute your query only the users with sufficient permissions will be able to get this data
The second option is when you want to avoid relationships here you can use the select option under query. Select allows you to select specific fields of the class and the query will return only the fields that you specified under the select. here is a code snippet from parse docs which explain how to use select (in JS):
var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
query.select("score", "playerName");
query.find().then(function(results) {
// each of results will only have the selected fields available.
});
Hope its clear now :)

How to prevent user from modifying some fields on the form?

I am using MVC3 and EF4 to write a web application. I am using an action header like below to capture the form values submitted by the user.
<HttpPost()>
Public Function Edit(ByVal prod as Product) As ActionResult
I use the below code for updating the record.
db.Attach(prod)
db.ObjectStateManager.ChangeObjectState(prod, EntityState.Modified)
db.SaveChanges()
I get the submitted values in prod object which I update in the database. The problem is that there are some users who are not allowed to modify certain fields in a Product, say ProductCost. I have disabled the textboxes for such fields in the HTML. But since it is clientside, the user can easily enable it using some tool like Firebug and modify the value.
The only solution I could come up was to retrieve the existing record from the database and copy its ProductCost value into prod.ProductCost. But I don't like firing a query for achieving this. Is there a better way to achieve this?
Edit: I found the below link to update particular fields. How to update only one field using Entity Framework?
You can use the below code to modify a particular field.
context.ObjectStateManager.GetObjectStateEntry(user).SetModifiedProperty("FieldName");
Now the question is do I have to write the above statement for every field the user is able to modify? If yes, suppose the Product model has 10 fields (1 primary key) and the user is allowed to modify all of them except the primary key, I need to write 9 statements?? Is there a method where you can specify multiple properties at once. Or even better something where you specify the properties which are not modified. (Note: I know I can run a loop over an array of field names to avoid writing 9 statements. I am asking for an alternative method and not refactoring the above)
Never trust client data. Always have your server code to validate the input and do appropriate actions.
I would create separate overloads of my Respiratory method update the product in different ways and then check what is the current user's access type, If he is admin, i will call the overload which updates everything, if he is a manager, i will call the method which updates name,imageUrl and price and if he is an employee, i will call the method which updates only name and ImageURL
[HttpPost]
public ActionResult Edit(Product prod)
{
if(ModelState.IsValid)
{
string userType=GetCurrentUserTypeFromSomeWhere();
if(userType=="admin")
{
repo.UpdateProduct(prod);
}
else if(userType=="manager")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl, prod.Price);
}
else if(userType=="employee")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl);
}
return RedirectToAction("Updated",new {id=prod.ID});
}
}

Resources