Do I have to add loopback-component-passport's core models manually? - passport.js

I installed loopback-component-passport so I can use it with strongloop's Loopback framework. I followed the docs,
but after this command: npm install loopback-component-passport, the following files/models are not created:
UserIdentity model
UserCredential model
ApplicationCredential model
These files are used by Loopback for third-party authentication. Do I have to add them manually? Or am I doing something wrong?

Yes, you have to add them manually. You can refer this example, loopback-example-passport on github.
The reason is the relationships of loopback-component-passport's core models i.e UserIdentity model, UserCredential and ApplicationCredential with Loopback's core model AccessToken and User doesn't come preconfigured which is required for authentication.
Also, you might notice that the developer extended the models but didn't added any model.js. This is so because there was no need to add any runtime logic. For starters, you might want to extend the core models as per the example and create relationship and acls only. Then you can proceed with custom logic.

I think loopback built in models stay tucked away in node_modules, so assuming you mean that these tables are missing from your datastore, you can do an autoupdate in order to get loopback to build any missing tables.
I add the following code to a file in the server/boot directory when I need to during development.
module.exports = function(app, done) {
app.datasources.mysql_db.autoupdate(function(err) {
if (err) throw err;
console.log("autoupdate");
done();
})
}
Where mysql_db is the name of your datastore.
This will update the datasource when the server boot but shouldn't drop existing data (saying that I have seen instances where foreign keys are lost, so care & db backup is still needed).

Related

Are migrations really needed in NodeJS Sequelize?

In Sequelize, when we create a model using the following command,
sequelize model:generate --name Company --attributes name:string, desc:text
A migration file is also getting created. And we can make the models sync with the DB by adding the following piece of code.
models.sequelize.sync().then(() => {
console.log("DB Synced");
}).catch((error) => {
console.log(error);
});
Therefore, when there's a change in the column names or something, they get synced with the DB.
So, do we really need to run migration ? At any point in the development or production ?
Please correct me if I am mistaken.
I strongly recommend to use explicit migrations and to point tables for storing applied migrations and seeds in a sequelize config in case you have different versions of a database in different production environments (even if you are just planning different production deployments).
If you run a newer version of your app with some model changes on an older production DB then by executing sync method you change this production DB accidentally. Moreover you cannot reverse these changes easily because you don't know anything about differences between models in your current app and tables in the production DB.

Can a Node package require a DB connection?

As per the title, can a Node.js package require a database connection?
For example, I have written a specific piece of middlware functionality that I plan to publish via NPM, however, it requires a connection to a NoSQL database. The functionality in its current state uses Mongoose to save data in a specific format and returns a boolean value.
Is this considered bad practice?
It is not a bad practice as long as you require the DB needed and also explicitly state it clearly in your Readme.md file, it's only a bad practice when you go ahead and work without provide a comment in your codes or a readme.md file that will guide any other person going through your codes.
Example:
//require your NoSQL database eg MongoDB
const mongoose = require('mongoose');
// to connect to the database. **boy** is the database name
mongoose.connect('mongodb://localhost/boy', function(err) {
if (err) {
console.log(err);
} else {
console.log("Success");
}
});
You generally have two choices when your module needs a database and wants to remain as independently useful as possible:
You can load a preferred database in your code and use it.
You can provide the developer using your module a means of passing in a database that meets your specification to be used by your module. The usual way of passing in the database would be for the developer using your module to pass your module the data in a module constructor function.
In the first case, you may need to allow the developer to specify a disk store path to be used. In the second case, you have to be very specific in your documentation about what kind of database interface is required.
There's also a hybrid option where you offer the developer the option of configuring and passing you a database, but if not provided, then you load your own.
The functionality in its current state uses Mongoose to save data in a specific format and returns a boolean value. Is this considered bad practice?
No, it's not a bad practice. This would be an implementation of option number 1 above. As long as your customers (the developers using your module) don't mind you loading and using Mongoose, then this is perfectly fine.

How to programmatically detach a model from a loopback application?

I am using loopback without the strongloop framework itself, meaning I have no access to any of the cli tools. I am able to succesfully create and launch a loopback server and define/load some models in this fashion:
var loopback = require('loopback');
var app = loopback();
var dataSource = app.dataSource
(
'db',
{
adapter : 'memory'
});
);
var UserModel = app.loopback.findModel('User');
UserModel.attachTo(dataSource);
app.model(UserModel);
/* ... other models loading / definitions */
// Expose API
app.use('/api', app.loopback.rest());
What I would like to achieve is to be able to detach a model from the loopback application at runtime, so it is not available from the rest API nor the loopback object anymore (without the need to restart the node script).
I know it is possible to remove a model definition made previously from the cli:
Destroy a model in loopback.io, but this is not valid in my case since what it does is to remove the json objects that are loaded at strongloop boot, which is not applicable here.
I would appreciate very much any help regarding this, I have found nothing in the strongloop API documentation.
Disclaimer: I am a core developer of LoopBack.
I am afraid there is no easy way for deleting models at runtime, we are tracking this request in issue #1590.
so it is not available from the rest API nor the loopback object anymore
Let's take a look at the REST API first. In order to remove your model from the REST API, you need to remove it from the list of "shared classes" maintained by strong-remoting and then clean the cached handler middleware.
delete app.remotes()._classes[modelName];
delete app.remotes()._typeRegistry._types[modelName];
delete app._handlers.rest;
When the next request comes in, LoopBack will create a new REST handler middleware and rebuild the routing table.
In essence, you need to undo the work done by this code.
In order to remove the model from LoopBack JavaScript APIs, you need to remove it from the list of models maintained by application's registry:
delete app.models[modelName];
delete app.models[classify(modelName)];
delete app.models[camelize(modelName)];
app.models.models.splice(app.models.indexOf(ModelCtor), 1);
(This is undoing the work done by this code).
Next, you need to remove it from loopback-datasource-juggler registries:
delete app.registry.modelBuilder.models[modelName];
Caveats:
I haven't run/tested this code, it may not work out of the box.
It does not handle the case where the removed model has relations with other models.
It does not notify loopback-component-explorer about the change in the API
Update
There's now a function called deleteModelByName that does exactly that.
https://apidocs.strongloop.com/loopback/#app-deletemodelbyname
https://github.com/strongloop/loopback/pull/3858/commits/0cd380c590be7a89d155e5792365d04f23c55851

Extending the users package of mean.io

I am trying to create an application for sports event management system using MEAN.io
Since it uses the modular approach, there are different packages that comes in skeleton application like system, users, access. What i want to do is make a new package called players and it should extend the users package. The players schema would contain extra fields section and teams.So how do I extend the User Schema of users package in players package?
You can make your players package be dependent on users.
Players.register(function(app, auth, users, database) {...});
You now have access to the database and can load the user schema with
var userModel = database.connection.model('User');
and you can use the schema.add function to extend the schema
userModel.schema.add({ scrore: 'string'});
This should add the score field to the user model
I think this might work for you. But I was told from a member of mongoose team that schema.add only works before compiling the model. See this link for more info about schema add http://mongoosejs.com/docs/api.html#schema_Schema-add

CRUD blueprint overriding in sails.js

According to this closed issue in sails:
https://github.com/balderdashy/sails/issues/835
CRUD Blueprint Overrides
"absolutely, this is coming in v0.10"
I'd like to modify the blueprints in my sailsjs service to allow named roots (consuming in ember).
Currently I'm having to customize every controller I create with actions that are largely duplicates of what is already in the blueprints.
I suspect that I can move this code out of my controllers now and into a blueprints override area, but I'm not clear on where to put that code.
Any examples or even just a pointer to the relevant code in sails the .10 repo would be greatly appreciated.
Update
In order to override blueprints in Sails 1.0 in the manner described below, you must first install the "custom blueprints" plugin for your project (npm install sails-hook-custom-blueprints).
To override blueprints in Sails v0.10, you create an api/blueprints folder and add your blueprint files (e.g. find.js, create.js, etc.) within. You can take a look at the code for the default actions in the Sails blueprints hook for a head start.
Adding custom blueprints is also supported, but they currently do not get bound to routes automatically. If you create a /blueprints/foo.js file, you can bind a route to it in your /config/routes.js file with (for example):
'GET /myRoute': {blueprint: 'foo'}
you can add actions with these names inside your controller to override default behaviour
to change destroy behavior
module.exports = {
destroy: function(req,res){
Goal.update({ id: req.param('id') }, { deleted: true })
.exec(function (err, goal) {
if (err) return res.json(err, 400);
return res.json(goal[0]);
});
}
}
It is possible to use the build in blueprints, but with policies running first. These policies might verify that the user is logged in, has the correct access, or similar. Really handy!
On each model, you have available callbacks both before and after data has been stored. Dig in: http://sailsjs.com/documentation/concepts/models-and-orm/lifecycle-callbacks
There is no default callback available for blueprints result. But don't give up. It is still possible to use the build in blueprints, and only modify the output. It might not be the most elegant solution, but it works well. Check out my “hack” here: Sails blueprints lifecycle

Resources