angularjsauthenticationionic-frameworkbackand

Backand user model vs registered users


I need to specify additional fields beyond firstName, lastName and email, which seem to be all that is returned to me when I call Backand.user.getUserDetails() in my app, despite having specified further fields in the model. So it seems that it is pulling these out of the "registered users" as opposed to the "users" model?

I also want to be able to allow a user to update these fields. But of course I don't want a user to be able to update the fields of others, which is what running an UPDATE on any of the model items with role "User" seems to be capable of doing.

Is there a lot of server side functionality I need to add to achieve this or is my approach here the wrong one - really would have assumed Backand would have this covered out of the box?


Solution

  • There seems to be a few questions in here, so let me do my best to address all of them. There are two types of user objects in Backand - registered_users, which consist of the authentication entity given permission to work with the Backand application, and users, which is a database object in a Backand app just like any other. The registered_users table is designed only to manage details relevant for authentication and assigning a security role to a user - app-specific data should be stored in the users object in your data model.

    The Backand platform uses security actions to attempt to maintain a linkage between these two tables. This means that (if you have not modified the default actions) the platform will create a new entry in the users object when a user registers, delete that user from the users object when they are deleted from the app, and it will try to push any updates received through to the users object. While you can't modify the registered_users object to add or remove fields, you can supply a hash of parameters that the action will use to populate the Users object. This parameter has has a fairly straightforward format of "column": "value", where column is the name of a column in your app's custom users object, and value is the value you wish to insert into that column. See http://docs.backand.com/#signup for more details

    Please note that if a field isn't present, or marked required but not provided, then the call will fail and create a discrepancy between users and registered_users.

    One of the goals we've had is to place as few restrictions on developers as possible - our above approach is indicative of that. We have to handle a number of different potential use cases, and not all of them are helped by a deeper integration with a users object - doing so would make the users object become a required component, affecting an app's schema and structures. Then adding security restrictions around ownership of the users object would only add hidden complexity - while it is necessary for your application, it isn't necessary for every application.

    Re: restricting edits to only objects owned by the user, there are a few approaches you can take to achieve this in Backand:

    1. Implement the protections entirely in app code on the client side. This gives you the most flexibility in terms of how to handle prevention of updates by unauthorized users.
    2. You can use a Pre-defined filter to filter the objects as they are retrieved for users with a non-admin role. It's available from the Security tab under Objects -> object_name. There's some documentation there on how to get started, but the most relevant portion is the "wizard" component at the top - the default code should do something very close to what you are looking for
    3. Use a custom action for each of the relevant database actions (create, update, delete) to prevent updates from users who don't own the object they are working with.

    Each approach has its positives and negatives. The first approach keeps the logic close at hand for your app, but doesn't protect against a malicious entity changing the parameters sent to Backand via the web request from the SDK. The second would work, but will apply globally in ways that may not be compatible with your application architecture. The third approach is the best compromise, but adds the complexity of managing the same code in multiple locations. There are strategies to get around this, but the right answer will heavily depend on your specific application's functionality and features.