Rails 4+: do not retrieve sensitive attributes from DB by default - ruby-on-rails-4

This a contrived example but I hope it demonstrates my question. No, I'm not storing passwords in plaintext, etc; this is just an example.
User.create(name: "John", password: "sensitive")
User.all => [{User: name: "John", password: "sensitive"}]
When I retrieve data from the DB, I do not want the password attribute returned by default, such that:
User.all => [{User: name: "John"}]
I assumed ActiveRecord would have a method in the model I could override to establish the default attributes to select, but I can't find such a method.

By default, Active Record loads all the attributes. There is no concept of "sensitive" attribute. In fact, as long as you don't dump the instance anywhere (e.g. using inspect), or you don't print out the attribute, there is really not a lot security issues associated with fetching that data (of course, assuming you have a secure connection).
Perhaps you should explain what is the issue that is bringing you to believe that not loading that attribute would be the best solution to the problem.
It's also important to remember that several Rails defaults will loop over all attributes, whenever you try to use features such as to_json. My suggestion is to avoid relying on those features, but always explicitly whitelist the attributes you want to use or export. That would prevent leakage of sensible details.
Last but not least, you can try to workaround the Rails defaults by using a method that enumerates all the attributes, without the ones you consider "sensible"
Model.select(Model.column_names - %w( password other )).all
select applies to any query method:
Model.select(Model.column_names - %w( password other )).find(54)
Model.select(Model.column_names - %w( password other )).first

Related

How to find out whether default value is used for Datastore ndb property?

Let's say we have a model like this:
class UserConfig(ndb.Model):
name = ndb.StringProperty()
email_subscriber = ndb.BooleanProperty(default=True)
Let's assume email_subscriber was set to default True by mistake and we want to fix that mistake and use default=False instead. I tried changing the value to default=False and that works fine for users created after that code is deployed, but that doesn't fix the problem for existing users.
Is there a way (e.g. some internal property which isn't documented in Datastore documentation), which would provide info whether given prop value was set explicitly by user or using the provided default.
I can write an upgrade which would set email_subscriber=False for all users, but I'm afraid some users might have intentionally checked this property in the app and wouldn't like to break their experience.
tl;dr: How can I determine if value in ndb object was set using the default for that property or was provided explicitly.
There is no way to know this. Once a value is set in the database there is no way to know which part of your code (ndb runs in your code from the database perspective) set the value.

How to initialize localForage for mobile app

I'm new to mobile development and plan to build an app using plain HTML & jQuery, with Onsen UI.
I read that we can use localForage as a database and have a few questions.
Is it mandatory to have a database name for my app. If no, then other apps in mobile may also be using localForage. Will the DB be same then for all apps.
The document here says, config should be called before each action.
So, is it ok if it is initialized on page load like this:
$(document).ready(function(){
localforage.config({
name : 'myApp',
version : 1.0,
storeName : 'keyvaluepairs'
});
});
or should it be declared before each action (get, set, clear etc.)
How can we know that the action is triggering the desired database, as it is not specified in the action methods.
Is it mandatory to have a store name.
Is it mandatory to have a database name for my app. If no, then other apps in mobile may also be using localForage. Will the DB be same then for all apps.
A: Yes and no. It is in fact mandatory to have a database name. However if you leave it unset, the default value "localforage" is used.
The document here says, config should be called before each action. So, is it ok if it is initialized on page load like this ...
A: Yes, it totally fine to init in $(document).ready(cb). In fact it's fine to "initialize" at any time, as long as you make sure it happens before the first ever call to any real action (setItem/getItem, etc.).
How can we know that the action is triggering the desired database, as it is not specified in the action methods.
A: localforage can have multiple instances, whereas each instance is bound to only one database, (more precisely, it's bound to a specific store of that specific database). You know the action is targeting a specific database, because these actions are methods of a specific instance. No ambiguity here.
I personally suggest you name your instance explicitly:
var myAppDb = localforage.createInstance({
// these are the same options accepted by localforage.config()
name: 'myApp',
version : 1.0,
storeName : 'keyvaluepairs'
});
myAppDb.setItem('foo', 'bar');
This way you're 100% sure the action is fired on "myApp" database ;-)
Is it mandatory to have a store name.
Again, yes and no. But wait, hear me out, this one is a bit tricky.
Whereas the default database is actually named "localforage", store in localforage has this strange internal concept of un-named default store. I personally find it very confusing. And it behaves quite quirky when you use LOCALSTORAGE as driver.
So the rule of thumb is always name your store. Just treat it like mandatory. If you have only one store in one database, maybe name it "default". Sound better than "keyvaluepairs" don't you think?
let instance = localforage.createInstance({
driver : localforage.INDEXEDDB, // Force WebSQL; same as using setDriver()
name : name,
version : 1.0,
size : 4980736, // Size of database, in bytes. WebSQL-only for now.
storeName : 'YourStoreName', // Should be alphanumeric, with underscores.
description : 'Your Description'
});
instance.setItem("key", {"name":"abc"});
**You can set config from createInstance as well **

Different Models for RESTful GET and POST

Does it violate the ideas of REST, or accepted conventions, to have different models for GET/PUT/POST at the same URL?
An example:
Consider a simple resource found at api/things
I can create a thing by:
POST api/things
with body = { Name: "New Thing" }
This returns me a thing along with location
{ Id: 500, Name: "New Thing", Links: ["api/things/500"] }
Location Header: api/things/500
I can get the thing with:
GET api/things/500
and I will get
{ Id: 500, Name: "New Thing", Links: ["api/things/500"] }
If I want to update it:
PUT api/things/500
{ Name: "Updated Thing", IsActive: false }
There are "rules" in this example that are hidden behind the different models.
When creating you can't specify the Id or IsActive setting. The Id is generated by the server always starts as Active.
You cannot update an Id, and thus the "link" which uses it, so the PUT model does not contain an Id field.
One strong criticism of this: I cannot do a POST to create a new one, change the Name field, and PUT it back to Update it. I would have to know to remove the Id and links fields. I could "be liberal in what I accept" and allow the Ids and Links to be on the PUT request, but then I need to make additional decisions like, "is it a 400 if the Id/Link they send is different?, and "is it a 400 if they don't send an Id/Link?". If the API claims to accept those fields on PUT, that could be seen as a contract that they are able to be updated.
It is perfectly valid to accept different DTO's for different methods. Quite often, a POST will create a new entity with default properties such as Id, StartDate or Active, etc. so these properties are not present on a "POST DTO". I tend to shy away from PUT's since the definition is you are replacing one entity with another, which could include an Id. I opt for PATCH in most cases where you are accepting deltas and partial objects. You can verify each property that was sent up and determine if it's a readonly property or not. In some cases, based on roles, it may be readonly for one user, and patchable by another. By following this, POST is one DTO, PATCH is partial, PUT is non-existent, and GET returns the full DTO.
I've only seen a couple places where PUT is useful. You want to change the binary of a file or you have a collection that you want to change, PUT is great. Otherwise, I love PATCH.

When are Strong Parameters used?

I understand strong parameters are used in cases where we are creating an object and putting it into our database. For example,
User.create(params[:user]) would have to be User.create(params.require(:user).permit(:name, :email, :password).
This is standard and simple to understand, however, are strong parameters required when updating a column or a few attributes in a model?
current_user.update_attributes(params[:user]). Does that have to be current_user.update_attributes(params.require(:user).permit(:name, :email, :password).
Lastly, I don't think it is needed for this case:
current_user.update_column(authentication_token: nil), but would it have needed to be updated if instead we had params = { authentication_token: nil }, and did current_user.update_column(params)?
Any time you pass an instance of ActionController::Parameters to one of the mass assignment apis (new, create, update_attributes, update etc.) you need to permit the appropriate fields.
In a controller the params method returns an instance of ActionController::Parameters, as are any hashes contained within it, so you need to use permit.
If you do
params = { foo: bar }
record.update_attributes(params) or
record.update_attributes(foo: bar)
Then you're passing a normal hash and so you don't need to use permit
Are strong parameters required when updating a column or a few
attributes in a model?
Yes, if the model is being updated with values from the end-user. Never trust the user input.
Suppose the current_user model has a 'role_id' column, which could be 1 for super user, 2 for normal user and 3 for guest. If you don't sanitize the parameters, the end-user could easily forge a request to gain privileges and compromise your application security.
Regarding your last question, you're right. You don't need strong parameters to update the record with values you already know.
I experimented on Rails 4 environment with both update and update_attributes method calls, and I received identical errors for both method calls: ActiveModel::ForbiddenAttributesError in PeopleController#update . In the controller I used #person.update(params[:person]) and #person.update_attributes(params[:person]); so that’s why it says PeopleController in the error message.
Based on the API documentation, it looks like in Rails 4 update_attributes is alias for update. So I guess update_attributes does the same thing as update method in Rails 4:
update_attributes(attributes) public
Alias for ActiveRecord::Persistence#update
Therefore, both update and update_attributes methods have to use strong parameters to update database. I also tested update_attributes method with strong parameters: #person.update_attributes(person_parameters) and it worked
updated
About update_attribute and update_column methods. I just tested those for the very first time through a controller, and with those methods you don’t need to use strong parameters inside of controller ( which was a bit surprise to me), even when you are using params (user provided values). So with update_attribute and update_column methods you can update database without using strong parameters.

Does Apache Thrift validate parameters?

I'm considering using Apache Thrift for a PHP server that implements web services.
If my web service were to be defined to accept two parameters - a user name as a string, and a password as an integer - would thrift validate that parameters of those types were supplied by the client, or do I still need to perform validation on the server?
I'm not asking here for the purposes of sanitising input, but rather for returning meaningful error responses to clients, and whether if a service is invoked with incorrect parameters requests will even be made to the server.
To my understanding, the check - if any - is performed at "library level", where the local types are translated into Thrift types, where the code generation happens. In other words, it will depend on the bindings for the specific language you are using (PHP, Erlang, whatever), to raise meaningful - or not - errors if types are not respected. But I have to look into it a bit more.
It basically depends on what kind of validation we are talking.
If the parameters need to be set, you could make them "required". In that case, the fields are checked in most language implementations (not in all) during deserialization and an error is thrown whenever a reuirwed Parameter is missing. However, required comes at the cost of potential problems with versioning: you can't omit a required field once the API has been published, or it will break compatibility otherwise.
The presence of normal ("optional") values can typically be checked by means of the _isset flags, which exist for exactly this purpose. This is something that your own code is responsible for - Thrift does provide the messaging mechanisms, but of course not the interpretation of your data.
If validation in your case means, that the data Format (string and number) should be checked: Because the code for both Client and Server is generated from the Thrift IDL file, the implementation will use the correct field serialization and deserialization method according to the IDL file:
Service sample
{
bool Login( 1: string Name, 2: i32 pwd)
}
If you Need to Change for whatever reason the Password from i32 into string, technically this results in two changes:
remove the Password field with the ID 2, except if the field is "required"
add a new field with the new ID 3
so it looks this way:
Service sample
{
bool Login( 1: string Name, /*2: i32 _deprecated_pwd*/, 3: string pwd)
}
As field type and field purpose are bound to the numeric field ID, it is highly recommended to use another field ID in such a case, which is so far unused within this scope. It is also recommended to leabve the old fields in the IDL to indicate outdated IDs.
A good reference about this "soft versioning" stuff and the pros and cons of "required" fields can be found in Diwaker Gupta's "Missing Guide".