calling method from external file in express routes - express

Hi I am new to expressjs. I have an admin route where I would like admin to update record and etc. I don't want to write code to updated record under the route rather I just to pass some functions or object that fetch records from db or updated them. I am using passportjs for authenticate. Currently my route look like this -
app.get('/admin', function(req, res){
res.render('admin', {
title: "Welcome Member_name ",
user: req.user
});
});
So I have created another js file for all admin operation. its under root/controller/admin.js and its looks like this -
var mysql = require('mysql'),
dbconfig = require('../config/database'),
connection = mysql.createConnection(dbconfig.connection);
module.exports = {
}
what I am after is to write some function that will get some data from the database and return the object so that I can pass the object to my route and from there to the view. Can anyone help me plz? thanks. Also if you know best practice for learning expressjs plz let me know. Thanks a lot in advance. Cheers.

I'll try to answer this one for you, although you question was a bit muddy to understand. If I'm right you'd like to call a method in your module from your route?
Let us say your module file was called admin.js for the following example. This is how you would create a method accessible outside of the module.
admin.js
var mysql = require('mysql'),
dbconfig = require('../config/database'),
connection = mysql.createConnection(dbconfig.connection);
module.exports = {};
module.exports.retrieveData = function() {
//Data retrieval code here.
};
Then in your routes file, let us say routes.js for the example. This is how you would call the method.
routes.js
var admin = require('./admin.js') //Remembering to require the module!
database.retrieveData();
You would then pass your query through a parameter in the retrieveData() method.

Related

Where do I execute native SQL queries in Loopback 4?

I'm new to Loopback 4 and I've been trying to execute a native SQL query. I found how to do it, the thing is that don't have any clue of WHERE to put it in my code in order for it to work... here's the documentation I found.
I need to know where should I put this:
const result = await repository.execute('SELECT * FROM Products');
in my Loopback project, which has many files. My goal is to make a REST endpoint like /products/[name] with [name] being a parameter inserted dynamically to the SQL query.
You can do it in your controller class as per loopback docs https://loopback.io/doc/en/lb4/Controller.html. As you will define the REST endpoint in the controller itself you can also do the insertion there using repository.execute() e.g.
#get('/products/{name}')
async doSomething(
#param.path.string('name') name: string,
): Promise<Product> {
const sql = `SELECT * FROM some_table WHERE some_field="${name}"`;
await this.productRepository.execute(sql)
--- other lines of code & return value --
}
Personally, I would implement it as a new Repository method.
Let's say your model is called Product, then you should have src/repositories/product.repository.ts file exporting ProductRepository class already present in your project. (You can run lb4 repository to create it.)
export class Product extends DefaultCrudRepository<
Product,
typeof Product,
Product Relations
> {
constructor(#inject('datasources.db') dataSource: DbDataSource) {
super(Product, dataSource);
}
// your custom method
async selectByName(name: string): Promise<Product[]> {
const rawItems = await repository.execute('SELECT * FROM Products');
// would you like to convert raw data into Product instances?
return rawItems.map(it => new Product(it));
}
}
Then you can call this new custom repository method from your controller in the same way as you would call e.g. repository.find(filter).

vuex-persistedstate not saving class methods

I'd like to preference this by saying my backgrounds in in C# so I like declaring methods within my classes. I've created a user class that contains properties and methods and I've added this to my vuex-persistedstate. One of the methods is a logout() method which clears out the properties. When I tried to invoke this method I got the following error:
TypeError: this.$data.user.logout is not a function
I then reviewed local storage and noted the user did not have reference to the class method. So I went ahead and copied the logic from the method into my vue component and it worked so I'm assuming the issue is vuex-persistedstate does not save references to methods which is why the method call did not work.
I'd like to declare the logout method in one location rather than spreading it out across vue components, what is the best practice for accomplishing this? Is it possible to do this in the class declaration or do I need a user helper file?
Sure Berco! My code is also up on GitHub so you can review it there too, but basically it seems to me that vuex does not store methods. The first file you should review is my user.js file:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/models/user.js
In this file I have a method called shallow clone which takes the info received from the API and assigns it to the user:
shallowClone(data) {
if (data !== undefined) {
this.id = data.id;
this.userName = data.userName;
this.firstName = data.firstName;
this.lastName = data.lastName;
this.nickName = data.nickName;
this.fullName = data.fullName;
this.email = data.email;
this.isActive = data.isActive;
this.isAdmin = data.isAdmin
this.isSuperUser = data.isSuperUser;
this.dateCreated = data.dateCreated;
this.dateUpdated = data.dateUpdated;
this.isLoggedIn = data.isLoggedIn;
}
}
You of course don't need to abstract this away but I've found it makes the code easier to maintain.
Then in the mounted() lifecycle hook I assign the user received from the API to the component user via the shallowClone method. Please bear in mind I've done additional work on this project and the login form is now it's own component which receives the user as a prop from the app:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/components/LoginForm.vue
mounted() {
let self = this;
window.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
self.authenticate();
}
});
this.$data.user = new User();
this.$data.user.shallowClone(this.$props.userForAuthentication);
},
The full code can be reviewed here:
https://github.com/Joseph-Anthony-King/SudokuCollective
I found a solution... I'm working on improving it. Basically I use the values pulled from localstorage into vuex to create a new user object in the vue component that has reference to the methods located in my user class declaration. I recalled recommendations that we should create clones of objects pulled from vuex for use within the vue component. I'm still refining the code but that's basic idea.

Auth0 hooks post-user-registration edit user_metadata

I created a post-user-registration hook, in which i would like to save some information to user_metadata. However, I don't see the data being saved
/*
#param {object} user.user_metadata - user metadata
*/
module.exports = function (user, context, cb) {
// Perform any asynchronous actions, e.g. send notification to Slack.
user.user_metadata = {
"someinfo": "abcd"
}
cb();
};
Something like:
module.exports = function (user, context, cb) {
var response = {};
user.user_metadata.foo = 'bar';
response.user = user;
return cb(null, response);
};
worked fine for me.
For rules the docs say that you can't directly update the user_metadata. As described on the link you have to use the updateUserMetadata function after you set the new values. I am not sure if this applies to hooks too (probably not, since the auth0 object is not defined on hooks).
p.s. Keep in mind that hooks only run for Database Connections, as outlined in the docs. Is there a chance you used an account based on social login?

Cloud Function retrieving a value based on URL parameter

I am trying to write a Cloud Function in node where I can return a token from a parameter.
The URL I use is...
https://us-central1-nmnm03.cloudfunctions.net/GetAccount?taccount=Asd
my function is this... and its wrong. I suspect I am not assigning TT properly.
var functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.GetAccount = functions.https.onRequest((req, res) => {
const t = admin.database().ref('/newaccout/'+req.query.account)
const tt = t.child(token)
res.send( "res is " + tt );
});
req.query.account is the Key. One of the Items in the document is token
ideally, I would like to get something like...
{"token":"23453458885"}
Could I get a node hint please... thanks
Though, I am not a firebase geek. What it seems from the documentation is that you will have two events that you can use to listen for retrieving child data. You can read further more here. The given options are used for different cases. Please follow through the mentioned link to have clear view.
Inside your cloud function you can try doing following:
const t = admin.database().ref('/newaccout/'+req.query.account)
t.on('child_added', function(data) {
res.json({
token: data.token
})
})
Or maybe like this:
const t = admin.database().ref('/newaccout/'+req.query.account)
t.once('value', function(snapshot) {
//Process it like above
//But here you will get al child elements at once
});
It looks like you are expecting to query the value found at a database reference stored at t. Unfortunately, you haven't actually performed a query yet. tt is just yet another Reference object that points to a location in the database. You should use the once() method on Reference to query a database location. Also bear in mind that you are using a variable called token, but you haven't defined yet in your code. To me, that looks like it would generate an error to me.
You might be well served by looking at a bunch of the sample code.

Aurelia: how to manage sessions

I'm trying to develop a website where the nav-bar items depend on the role of the user who is logged in.
As Patrick Walter suggested on his blog, I was thinking to create a session.js file where I would store information about the current user: their username and role. I would then inject this file in nav-bar.js and create a filter for the routes, for which the user does not have access to. Everything worked fine until I hit the refresh button... In fact, it creates a new session object and I loose all the information store in the previous one.
I have seen in the docs the singleton method, but I'm not sure how to use it. If I insert it in my code such as below, I get the message: aurelia.use.singleton is not a function.
import config from './auth-config';
export function configure(aurelia) {
console.log('Hello from animation-main config');
aurelia.use
.singleton(Session)
.standardConfiguration()
.developmentLogging()
.plugin('aurelia-animator-css')
.plugin('paulvanbladel/aurelia-auth', (baseConfig) => {
baseConfig.configure(config);
});
aurelia.start().then(a => a.setRoot());
}
export class Session {
username = '';
role = '';
reset() {
console.log('Resetting session');
this.username = '';
this.role = '';
};
}
My last idea would be to encrypt the role/username and use the browser's session to store the information. But I wanted to ask to more experienced developers their opinion about the topic.
Thanks for your help!
EDIT: Here is my code for session.js
export class Session {
username = '';
role = '';
reset() {
console.log('Resetting session');
this.username = '';
this.role = '';
};
}
And this is how I inject it:
import {Session} from './services/session';
#inject(Session)
export class RoleFilterValueConverter {
constructor(session) {
console.log('Hello from RoleFilter constructor', session)
this.session = session;
};
toView(routes, role) {
console.log('Hello from view', role, this.session)
if (this.session.role == 'Superuser')
return routes;
return routes.filter(r => {
var res = !r.config.role || (r.config.role == this.session.role);
return res
});
}
}
In the main entry point (let's assume it's index.html) you should have something like this:
<body aurelia-app="path/to/main">
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
This imports the entire aurelia enviorment and so when it reaches the export function configure(aurelia) { ... } it should pass an instance of type Aurelia and bind it to the aurelia parameter and should resolve your aurelia.use.singleton is not a function. error. After that, in your session.js file when using #inject(Session) it should pass the same instance you declared at startup.
I also implemented a singleton session object to store user data and have chosen this method because it's more convenient to rely on dependency injection rather than always calling a method to get user data from a cookie.
Though Laurentiu's answer is not bad, there are better ways to handle this that do not add complexity to your app.
You do not need to need to specify this as a singleton. This particular function is more for an edge case where you would want to expose a particular item to the dependency injection container as a singleton before startup.
In fact, the Aurelia dependency injection framework treats all modules as singletons unless specified otherwise. Thus, the code should work as you have it written there, without the configure function.
I've written up an in-depth blog that you maay find helpful here: http://davismj.me/blog/aurelia-auth-pt2/