Using build in model accessToken not working in loopback - node.js

I'm trying to begin programming an api for an android application and wanted to use node.js + loopback for this. But I'm running into some trouble testing/ learning the language.
Following code should generate new users in my database(and it does) but when I try to login with this user no AccessToken in created an printen to the console. Any idea what I'm doing wrong?
My Test code: create-test-data.js
var app = require('./app');
var dataSource = app.dataSources.mysql;
var loopback = require('loopback');
var User = loopback.User; // Getting User Model
var AccessToken = loopback.AccessToken; // Getting AccessTokenModel
/*
Initializing the database done by this. If already exist it will clean it.
dataSource.automigrate('user', function (err) {});
dataSource.automigrate('account', function (err) {});
dataSource.automigrate('accesstoken', function (err) {});
*/
//Creating some users in mysql database
User.create({username: 'timbo', email: 'test#gmail.com', password: 'monkey123'} , function(err, user) {console.log(user);});
User.create({username: 'timbo2', email: 'test2#gmail.com', password: 'monkey123'} , function(err,user) {console.log(user);});
User.create({username: 'timbo3', email: 'test3#gmail.com', password: 'monkey123'} , function(err,user) {console.log(user);});
User.login({username: 'timbo', password: 'monkey123'}, function(err, accesstoken) {console.log("This is the token: " + accesstoken);});
//No accesstoken created / saved in the database
datasource.json
{
"db": {
"defaultForType": "db",
"connector": "mysql",
"host": "127.0.0.1",
"database": "test",
"user": "root",
"password": "warcraft"
},
"push": {
"defaultForType": "push",
"connector": "loopback-push-notification",
"installation": "installation",
"notification": "notification",
"application": "application"
},
"mail": {
"defaultForType": "mail",
"connector": "mail"
},
"mysql": {
"connector": "mysql",
"host": "127.0.0.1",
"database": "test",
"user": "root",
"password": "warcraft"
}
}
models.json
{
"email": {
"options": {
"base": "Email"
},
"dataSource": "mail",
"public": false
},
"user": {
"options": {
"base": "User",
"relations": {
"accessTokens": {
"model": "accessToken",
"type": "hasMany",
"foreignKey": "userId"
}
}
},
"dataSource": "mysql",
"public": true
},
"accessToken": {
"options": {
"base": "AccessToken"
},
"dataSource": "mysql",
"public": true
},
"application": {
"options": {
"base": "Application"
},
"dataSource": "db",
"public": true
},
"acl": {
"options": {
"base": "ACL"
},
"dataSource": "db",
"public": false
},
"roleMapping": {
"options": {
"base": "RoleMapping"
},
"dataSource": "db",
"public": false
},
"role": {
"options": {
"base": "Role",
"relations": {
"principals": {
"type": "hasMany",
"model": "roleMapping",
"foreignKey": "roleId"
}
}
},
"dataSource": "db",
"public": false
},
"scope": {
"options": {
"base": "Scope"
},
"dataSource": "db",
"public": false
},
"push": {
"options": {
"base": "Push",
"plural": "push"
},
"dataSource": "push"
},
"installation": {
"options": {
"base": "Installation"
},
"dataSource": "db",
"public": true
},
"notification": {
"options": {
"base": "Notification"
},
"dataSource": "db",
"public": true
},
"product": {
"properties": {
"email": {
"type": "string"
},
"level": {
"type": "number"
},
"create": {
"type": "date"
},
"modified": {
"type": "date"
}
},
"public": true,
"dataSource": "db",
"plural": "products"
},
"account": {
"properties": {
"email": {
"type": "string"
},
"level": {
"type": "number"
},
"created": {
"type": "date"
},
"modified": {
"type": "date"
}
},
"public": true,
"dataSource": "mysql",
"plural": "accounts"
}
}
Console Output
{ username: 'timbo',
email: 'test#gmail.com',
password: '$2a$10$972DFwMOuOhKj5ThfbchC.ipcNaW27ccpHMRkW17uSLutaCHyZF0G',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
{ username: 'timbo2',
email: 'test2#gmail.com',
password: '$2a$10$1peSixaOIQq8umOzzEy86OQKxoPFU.Ax2/NWC1oLGjQHPp9oZdPDW',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
{ username: 'timbo3',
email: 'test3#gmail.com',
password: '$2a$10$X3fdV2dL6kjuj69Dqr.jMeVdqIMzveN7NnJP5TXag54b4tpzZ4LGW',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
This is the token: undefined
This is the token err: Error: ER_BAD_FIELD_ERROR: Unknown column 'ttl' in 'field list'

You have to attach User-related models to your datasource first:
loopback.User.attachTo(dataSource);
loopback.AccessToken.attachTo(dataSource);
loopback.Role.attachTo(dataSource);
loopback.ACL.attachTo(dataSource);
And define the relationship between User and AccessToken:
loopback.User.hasMany(loopback.AccessToken, {as: 'accessTokens'});
When creating test data, you should wait for User.create to finish before calling User.login. (Rember, Node.js is asynchronous.)
User.create(
{username: 'timbo', email: 'test#gmail.com', password: 'monkey123'},
function(err, user) {
// TODO: handle err != null
User.login(
{username: 'timbo', password: 'monkey123'},
function(err, accesstoken) {
console.log("This is the token: " + accesstoken);
});
});

Related

How to access Mongoose nested document populate fields using typescript

how can I access the fields like create, update to check whether it is enabled or not using mongoose and typescript?
_id: "62138fc713ea5c49fd61d3f0"
employeeId: "IN0201"
email: "user2#dddd.com"
password: "$2b$10$eEM222UB2/7ugbw1krAiNON3zDGUnYTifLsrZ2FNXoq/NhzWANNdS"
mentor: "62138151cd614d1d1c7eaa2b"
role: [
{
"_id": "621322240e7e69371aabf4e6",
"roleName": "user",
"permissions": {
"modules": [
{
"user": {
"create": {
"name": "create",
"enable": false
},
"update": {
"name": "update",
"enable": true
},
"view": {
"name": "view",
"enable": true
},
"delete": {
"name": "delete",
"enable": false
}
},
"events": {
"create": {
"name": "create",
"enable": false
},
"update": {
"name": "update",
"enable": false
},
"view": {
"name": "view",
"enable": true
},
"delete": {
"name": "delte",
"enable": false
}
},
"_id": "62137c1728df74de4255ca71"
}
],
"_id": "62137c1728df74de4255ca70"
}
}
]
status: "active"
deleted: false
createdAt: "2022-02-21T13:12:39.414Z"
updatedAt: "2022-02-21T13:12:39.414Z"
I don't know the exact name of your entity in the database, but let's assume it's Employer, you should be able to query using:
Employer.find( {"role.modules": { user: { create: true } } }, function(err, employer){
if(err){console.log(err);}
else{console.log(employer);}
});

Loopback Email Connector not sending emails

I have a Loopback Application with a REST API.
I want to make a REST API Enpoint /Email/sendEmail which sends an email. I did this tutorial: https://loopback.io/doc/en/lb3/Email-connector.html, but it's not working for me somehow.
When I open https://localhost:3000/explorer , I can see the API Endpoint and I can press the button "Try it out". But then it just loads forever and after a while I get a Timeout error in the console.
File: datasource.json
{
"db": {
"host": "localhost",
"port": 27017,
"url": "",
"database": "siemens",
"password": "",
"name": "db",
"user": "",
"useNewUrlParser": true,
"connector": "mongodb"
},
"email": {
"name": "email",
"connector": "mail",
"transports": [{
"type": "SMTP",
"host": "smtp.gmail.com",
"secure": true,
"port": 465,
"auth": {
"user": "xbit.dany#gmail.com",
"pass": "XXX"
}
}]
}
}
File: model-config.json
"Email": {
"dataSource": "email",
"public": true
}
File: email.js
module.exports = function(Email) {
// send an email
Email.sendEmail = function(cb) {
console.log("Sending Email");
Email.app.models.Email.send({
to: 'siemens.dany#gmail.com',
from: 'xbit.dany#gmail.com',
subject: 'my subject',
text: 'my text',
html: 'my <em>html</em>'
}, function(err, mail) {
console.log('email sent!');
cb(err);
});
}
Email.remoteMethod(
'sendEmail', {
http: {
path: '/sendEmail',
verb: 'get'
},
returns: {
}
}
);
};
File: models/email.json
{
"name": "Email",
"base": "Model",
"properties": {
"to": {"type": "String", "required": true},
"from": {"type": "String", "required": true},
"subject": {"type": "String", "required": true},
"text": {"type": "String"},
"html": {"type": "String"}
}
}
The mail is now working. This is the code of email.js
module.exports = function(emailDS) {
// send an email
emailDS.sendEmail = function(cb) {
console.log("Sending Email");
emailDS.app.models.Email.send({
to: 'siemens.dany#gmail.com',
from: 'xbit.dany#gmail.com',
subject: 'my subject',
html: 'my <em>html</em>'
}, function(err, mail) {
console.log("Mail: " + mail);
console.log("Error: " + err);
cb(null, mail);
});
}
emailDS.remoteMethod(
'sendEmail', {
http: {
path: '/sendEmail',
verb: 'get'
},
returns: {
arg: 'Status', type:'string'
}
}
);
};

got confused in loopback

hello guys i m new to loopback so please, can anyone help me with this following this
1. i know how to render html page from loopback server for eg:-
<form method="post" action="register">
<input type="text" name="name">
<input type="text" name="lastname">
</form>
how to can request name or lastname in my model user
'use strict';
module.exports = function(User) {
// how i can receive requested of name or lastname for eg :-
console.log(req.name)
};
2.how i can insert this data to my postgres table(table name :-register) in column "name"
3.last one is that how to differentiate table name and model name using automigrate
module.exports = function(User) {
User.show = function(name,lastName) {
console.log(name);
console.log(lastName);
}
User.remoteMethod('show', {
accepts: [
{ arg: 'name', type: 'string' },
{ arg: 'lastName', type: 'string' }
],
returns: {arg: 'result', type: 'string'}
});
}
for the insert something like :
var yourVar = name;
pg.connect(dbUrl, function(err, client, done) {
client.query(
'INSERT into yourTable(name) VALUES ($1)',
['title'],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted');
}
});
});
depending on your table and log credentials
Edit :
to use auto migrate, you must first :
create a data source in /server/datasources.json :
"mydb": {
"name": "mydb",
"connector": "postgresql"
}
Connect to UNIX domain socket in /var/run/postgresql/.s.PGSQL.5432 :
{
"postgres": {
"host": "/var/run/postgresql/",
"port": "5432",
"database": "dbname",
"username": "dbuser",
"password": "dbpassword",
"name": "postgres",
"debug": true,
"connector": "postgresql"
}
}
define your models in /common/models/model.json, it shoud look like this :
var schema={
"name": "User",
"options": {
"idInjection": true,
"postgresql": {
"schema": "yourShema",
"table": "USER"
}
},
"properties": {
"id": {
"type": "Number",
"required": true,
"length": 64,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "id",
"dataType": "integer",
"dataLength": 64,
"dataPrecision": null,
"dataScale": null,
"nullable": "NO"
}
},
"name": {
"type": "String",
"required": false,
"length": 40,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "name",
"dataType": "character varying",
"dataLength": 40,
"dataPrecision": null,
"dataScale": null,
"nullable": "YES"
}
},
"lastName": {
"type": "String",
"required": false,
"length": 40,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "lastName",
"dataType": "character varying",
"dataLength": 40,
"dataPrecision": null,
"dataScale": null,
"nullable": "YES"
}
}
}
then you must call Model.automigrate() or Model.autoupdate() in your code like this :
ds.createModel(schema);
ds.autoupdate(schema) {
ds.discoverModelProperties('USER', function (err, props) {
console.log(props);
});
});
You will certainly have yo change some things but I hope you will achieve what you want ;)

Filter on level 2 properties

I use LoopBack with MongoDB connector.
Models:
Application for a job:
{
"name": "application",
"plural": "applications",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"jobId": {
"type": "string",
"required": true
},
"staffId": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Job:
{
"name": "job",
"plural": "jobs",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"title": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"applications": {
"type": "hasMany",
"model": "application",
"foreignKey": "jobId",
"primaryKey": "id"
}
},
"acls": [],
"methods": {}
}
If the user's id (staffId) is in the applications array I need to not show for user this job.
Example:
We have array of jobs with applications
[
{
id: 1,
title: "Job 1",
applications: [
{
jobId: 1,
staffId: 1
},
{
jobId: 1,
staffId: 2
}
]
},
{
id: 2,
title: "Job 2",
applications: [
{
jobId: 2,
staffId: 1
}
]
}
]
If user's id (staffId) is 2 then user sees only "Job 2".
I tried something like this:
/jobs?filter[include][applications]&filter[where not][applications][elemMatch][staffId]=2
But it doesn't work.
Any suggestions?
Thanks.
At this state of the development you can't filter on a level 2 properties with REST: https://github.com/strongloop/loopback/issues/517 (defect till 2014).
What you can do instead is to define a custom emote method that will contain something like:
var userId = 2;
Jobs.find({
include: {
relation: 'applications',
scope: {
where: {staffId: {eq: userId}},
}
}
}, function (err, jobs) {
});

loopback hasandbelongstomany relation table doesn't exist

I have defined two models:
a 'part' model:
{
"name": "part",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string"
}
},
"validations": [],
"relations": {
"assemblies": {
"type": "hasAndBelongsToMany",
"model": "assembly",
"foreignKey": ""
}
},
"acls": [],
"methods": {}
}
and an 'assembly' models:
{
"name": "assembly",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"title": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"parts": {
"type": "hasAndBelongsToMany",
"model": "part"
}
},
"acls": [],
"methods": {}
}
both models have an hasAndBelongToMany relation.
In a /server/boot/sample-model.js i have created some instance of this both models:
module.exports = function(app){
var Dev = app.dataSources.dev;
var Customer = app.models.customer;
var Order = app.models.order;
var Part = app.models.part;
var Assembly = app.models.assembly;
Dev.automigrate(['customer', 'order', 'assembly', 'part'], function(err) {
Customer.create([
{name: 'nicolas'},
{name: 'marie'},
{name: 'cyril'}
], function(err, customers){
Part.create([
{name: 'boulon'},
{name: 'ecrou'},
{name: 'cheville'},
], function(err, part){
//console.log(part[0])
Assembly.create([
{title: 'piece1'},
{title: 'piece2'},
{title: 'piece3'},
], function(err, assemblies){
//console.log(assemblies[0])
assemblies[0].parts.add(part[0], function(err){
if(err){
console.log(err)
}
})
})
})
});
});
}
but
assemblies[0].parts.add(part[0], function(err){
if(err){
console.log(err)
}
})
end with error:
{ [Error: ER_NO_SUCH_TABLE: Table 'database_development.assemblypart' doesn't exist]
code: 'ER_NO_SUCH_TABLE',
errno: 1146,
sqlState: '42S02',
index: 0 }
why loopback doesn't create the assemblypart table in my database ?
I ran into this same issue once and after many hours of struggling (using postgres connector), I've found several solutions.
Here's the shortest :
Instead of :
Dev.automigrate(['customer', 'order', 'assembly', 'part'], function(err) {
// Your code here
});
Try using this :
Dev.automigrate()
.then(function(err) {
// Your code here
});
I don't know exactly why, but in the second case the junction table is created.
Can you try this and let me know if it works for you ? If it's not can you provide some place where I can inspect and try running your code ?

Resources