Loopback: How to isolate a users queries to a specific datasource? - loopbackjs

Let's say I have two users, A and B, with IDs 1 and 2 (respectively). Further, let's assume I have two datasources configured: X and Y.
How could I isolate ALL queries issued by user A to datasource X, and all by B to Y for some given remote method? For example, say that A wants to run 'find' for some model via the API - how could I make sure that the only results A will get are those which are accessible through datasource X?

I'm not sure I entirely understand why you would decide a datasource based on the current user, but in any case, I'm not sure you can do that with LoopBack ... at least, not easily. LoopBack is a model-driven framework - everything derives from the model. As such, all API endpoints go through a model (although you can set up custom routes). And each model is connected to a single datasource.
So, if I hit /api/Widget/13 there is no way to make that findById() call switch between two datasources, it will always hit whatever datasource the model is connected to.
Okay, that all said, the solutions I see are to:
Create a "dispatcher" and have that model do the appropriate thing.
Create a custom remote method on your existing model and do the decision making there and the find, etc on the correct datasource.
In either case, it's not straightforward, and not built-in. FYI, if you need to get the datasource you can access it from the LoopBack application object: MyModel.app.datasources.ds1

Related

How to move the data from one DynamoDB table to other DynamoDB table in the same region on click of HTML button

I am very new to AWS. As the first step I am creating an eCommerce application on my personal interest to give the demo of this application to my colleagues.
I am implementing 'Order' part. For this, I am thinking of moving the data from one table to other. I.e Once the user add the product to cart , it will saved in Cart table in dynamo-db and in cart screen when the user clicks on 'Order'button/Link, the same data as it is in cart table should be moved to Order table and the cart should be empty So, the order can be confirmed.
How could I implement it? Not sure the method I am thinking is right if there any other method to accomplish Order functionality.
The answer to this is really going to depend on your architecture and stack - and even within that you have lots of options.
In a serverless way, i.e. from a static html page with no server-side backend, you could create a lambda function in the supported language of your choice and with the proper IAM role, to move the data from one table to the other - your html page could call it via an API call, and I would suggest you use AWS API Gateway to expose an api endpoint that then calls the lambda function.
If on (one of the other many) other-hands, say you were using ASP.net or PHP on the server side, you could use the AWSSDK to talk to the dynamodb directly and accomplish the same thing.
Besides these two options there are many, many alternatives and variations - and with all of the options you are also going to need to deal with authentication/security to make sure no one can make calls to your database/service that they aren't permitted to - perhaps not important for your demo application, but will definitely be an issue if/when you go live.

Loopback default values for missing properties when fetching data from MongoDB

How should I define the Loopback model so that all the properties listed in the model JSON file would always appear on the result even when those properties have no value (or are missing) from the MongoDB record? Should this behaviour be configured in the Loopback or in the MongoDB?
Thanks!
MongoDB is a Schema-less database. It is designed in this way to give us flexibility for adding new fields to a document without any need to restart the database. So I don't think that it is a good idea to handle this scenario on the database side.
I think the best way to handle this could be setting a default value for every property in LoopBack model definition. This solution has a problem when some data is inserted into the database from outside the project.
You can also handle missing parameter at the front-end side.
Another solution that I can think of, is implementing an afterRemote method for checking the existence of all the fields. In this case, you can use this function after any API route that you want to. You can check the following link for more information:
https://loopback.io/doc/en/lb3/Remote-hooks.html#signature

How to add additional information to ember models

I am looking to have additional data added onto my models after the JSON data is returned from the service. The service I talk to returns information as a code, but I want to also include a more readable name to display to users. This would be done almost everywhere the model is used.
Example:
Fetch from the service
{schedule: {code:'MONTHLY'}}
Have access to
{schedule: {code:'MONTHLY', name: 'Monthly'}}
This would be for things which have a map of code to name, where name only ever lives on the front end, and code is what is persisted. I see there is a concept of custom transforms, would this be the way to go?
I also plan to keep a mapping of all possible codes/names in another file, to iterate over or compare to the model's attributes. For instance I would want to present users with a choice of schedules to choose from, MONTHLY, QUARTERLY, or ANNUALLY.
You should create a Computed Property on a model. You can call it: "name" or "displayName". It should depend on "code" attribute on model. Inside computed property, you should access a service. Service should have a method to map code -> name. A method you call from the model on service should return you a name. A code-name map should be separated from the model.
Whenever you want to access displayName Computed Property from model use model.displayName.

Accessing a distant relation using $owner in loopback

I just started using loopback, and I am stuck with ACL. My database has a relation like so:
User has many tests and tests have many users ( many to many, in loopback I am using hasmanythrough).
Each test has several sections (one to many)
Each section has several question(one to many)
Now, I want to get all sections that a user has , or all questions that a user has. I know that using $owner needs a belongsTo in the respective model, but in my case that is not possible.
Is there any way to achieve this without having to completely write my own queries ?
Unfortunately the $owner role doesn't work as a filter, but as security access to end-points when an instance ID is specified; basically it only works when you perform a findById, but not when you perform a find.
Example:
GET /api/tests/ does nothing. The current user sees ALL The tests. No filtering is performed
GET /api/tests/{id} checks that the currently logged in userId corresponds to the userId in the test you are trying to retrieve. If the userIds match, then the user can view this particular test. if they do not match then you get an AUTHORIZATION_REQUIRED or ACCESS_DENIED error (I can't remember which).
as I just wrote in this question, you might want to look at creating a Mixin.

Filtering of data according to user logged in Django app

I have a Django app that works well for me, but currently has no notion of user: I am the only one using it, and I would like to change this...
Except for the admin views, the logged-in user should not have access to the data created by other users. There is no shared data between users.
I suppose I have to add a user foreign key to all the models I created. Correct?
Is there a simple way to implement the filtering based on request.user? Can this be done more or less automatically, or do I have to go through all the code to check each and every query done on the database?
I have written the code using TDD, and I intend to follow up... What are the best strategies to ensure that user-filtering is implemented correctly, e.g. that I did not forget to filter an existing query? I suppose I can write tests that show that a particular query is not yet filtered, and implement the filter. But what about the queries that I will write later? Is there a way I can assert that all existing and future queries return objects that only belong to the current user?
Thanks.
Yes, you'll need to add a User FK. Don't forget you'll have to migrate your database tables - either manually, or via a tool like South.
One way of implementing the filter would be to define custom Managers for your models, with a for_user method that takes the User as an argument: something like:
class ForUserManager(models.Manager):
def for_user(self, user):
return self.filter(user=user)
Now you can use this manager - subclassed and/or with a mixin as necessary - on all your models, and remember to use objects.for_user(request.user) everywhere.
This will make testing easier too - your test could monkeypatch that for_user method so that it sets a flag or a counter in a global variable somewhere, and then test that it has incremented as expected.
Edit in response to comment No, as you suspect, that won't work. It's not even that everyone will necessarily get the last-logged-in user: it's that Managers are class-level attributes, and as such are reused throughout a process, so any request served by that server process will use the same one.