Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent certain fields from being overwritten with PATCH in .NET Azure Web Api

I am creating an Azure Mobile Service with a .NET backend which uses a TableController (subclass of ApiController) to handle REST requests.

In my PATCH method I want to restrict the set of fields that are allowed to be updated. I have an AccountController where I don't want the fields Username and UserId to be overwritten.

public class AccountController : TableController<Account>
{
...
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
   public Task<Account> PatchAccount(string id, Delta<Account> patch)
   {            
            return UpdateAsync(id, patch);          
   }
...
}

I would like to send back a meaningful HTTP response like 403: Forbidden or similar if a client connecting to the API tries to update the username or userId. So I need some way of either knowing the content of the Delta patch or having an auto response when the 'forbidden' fields are being updated.

like image 848
Daniel Avatar asked Nov 21 '14 11:11

Daniel


1 Answers

Not sure if there is a built-in way to do that. However, you can workaround this. Create new attribute, let's say NonEditable.

public class NonEditableAttribute: Attribute 
{
}

Apply this attribute to properties you don't want to be patched.

public class Account
{
   [NonEditable]
   public string UserName {get;set;}

   ... other properties
}

Write some helper method that will check if changed properties on Delta<T> contains any of these non editable properties.

public bool IsValidDelta<T>(Delta<T> delta) where T: class
{
   // list of property names that can't be patched
   var nonEditablePropertyNames = from p in typeof(T).GetProperties()
                    let attr = p.GetCustomAttribute(typeof(NonEditableAttribute))
                    where attr != null
                    select p.Name;
   // list of property names that were changed
   var changedPropertyNames = delta.GetChangedPropertyNames();

   // check if changedPropertyNames contains any of propertyNames, 
   // if yes return false, if no return true;
}

Now, in your ApiController, just check if Delta<T> contains changed properties, that are not editable

public class AccountController : TableController<Account>
{
...
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
   public Task<Account> PatchAccount(string id, Delta<Account> patch)
   {    
       if(IsValidDelta(patch))        
            return UpdateAsync(id, patch);          
       else
          // forbidden...
   }
...
}

Please Note: Code is not tested, and can be better designed. This is to give you general idea - treat it as pseudo code.

like image 169
Michael Avatar answered Oct 16 '22 20:10

Michael