How to load routes from DB in Meteor before everything? - mongodb

I have this code to create routes from database in Meteor:
if (Meteor.isClient) {
Meteor.subscribe("routes", function() {
Routes.find({}).map(function(route) {
try {
Router.route(route.path, {
name: route.name,
waitOn: function() {
var subscribes = [];
if (typeof route.subscriptions== 'object' &&
route.subscriptions
.length > 0) {
route.subscriptions.forEach(function(subscription) {
subscribes.push(Meteor.subscribe(
subscription));
});
}
return subscribes;
},
action: function() {
this.render(route.template);
}
});
} catch (e) {
console.log("Error: " + e);
}
});
});
}
So when I type in browser a path to a route from db gives this error:
Oops, looks like there's no route on the client or the server for url: "https://localhost:3000/menus."
I think its because this code runs after pageloads. How can I work around it?

Related

ldapjs handling client.search response

I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?
const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
// Connect and bind to the Active Directory.
const connectToClient = async () => {
const secret = LDAP_SECRET_KEY;
return await new Promise((resolve, reject) => {
client.bind(LDAP_USER, secret, function (err, res) {
if (err) {
console.error(err);
reject('Failed to connect to LDAP server');
} else {
resolve('Connected to LDAP server');
}
});
});
};
onst searchADForUser = async () => {
return await new Promise((resolve, reject) => {
client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
if (err) {
console.error(err);
reject('Error searching LDAP server');
} else {
res.on('searchEntry', function (entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
});
resolve(res);
}
});
});
};
const handler = async (event) => {
try {
return responses.success(
await connectToClient().then(async function(event) {
console.log(event);
await searchADForUser().then(function(event) {
console.log(event);
}).catch(function(event) {
console.log(event);
})
}).catch(function(event) {
console.log(event);
})
);
} catch (err) {
console.error(err);
return responses.error(err);
} finally {
client.unbind();
}
};
The active directory structure is below
The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.
Code I am now using below:
function (err, res) {
if (err) {
console.error(err);
reject(new Error('Error retrieving users from Active Directory'));
} else {
const entries = [];
res.on('searchEntry', function (entry) {
entries.push(entry);
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
if (result.status !== 0) {
reject(new Error('Error code received from Active Directory'));
} else {
resolve(entries);
}
});
}
}

My mongoDB api is getting a webtask.io token error

I'm learning about webtask.io and so I've coded a simple REST api (I'm not using Express.js here but maybe I should). It's a little webtask.io app that connects to an mlab MongoDB database and retrieves todos from a tasklist collection. The issue is that I'm getting this error:
{"code":404,"message":"unable to resolve jtn to webtask token","req_id":"1504385487318.83712"}"
Any idea how to fix this error? Here is a snippet of my code:
var MongoClient = require('mongodb').MongoClient;
...
module.exports =
function (ctx, req, res) {
// write the header and set the response type as a json
res.writeHead(200, { 'Content-Type': 'application/json' });
MongoClient.connect(ctx.data.MONGO_URL, function (err, db) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.CONNECT_ERROR));
} else {
switch(req.method) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.GET_ERROR));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
//post, delete, and put are in here
} //switch
} //else no error
db.close();
}); //Mongo connect
res.end();
} //export function
I decided to try using Express and now I'm able to run my little webtask.io without having to have a web token. I'm not sure why my first try required one and if I find that answer I will post it. Here is my working version:
/* express app as a webtask */
var MongoClient = require('mongodb').MongoClient;
var Express = require('express');
var wt = require('webtask-tools');
var app = Express();
var assert = require('assert');
var ObjectId = require('mongodb').ObjectId;
app.use(require('body-parser').json());
function doCRUD (crudType,req,res) {
MongoClient.connect(req.webtaskContext.secrets.MONGO_URL,function (err, db) {
if (err) {
res.send(JSON.stringify(err));
} else {
switch(crudType) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.send(JSON.stringify(err));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
case 'POST':
db.collection('tasklist').insertOne({"tasklist" : req.query.todo, "dateAdded" : new Date()}, function(err, r) {
assert.equal(null, err);
assert.equal(1, r.insertedCount);
});
break;
case 'DELETE':
db.collection('tasklist').deleteOne({_id: new ObjectId(req.query.id)},function(err){assert.equal(null,err)});
break;
case 'PUT':
//not implemented for this hack
break;
}
}
});
}
// GET
app.get('*', function (req, res) {
doCRUD('GET',req,res);
});
// POST
app.post('*', function (req, res) {
doCRUD('POST',req,res);
res.end();
});
// DELETE
app.delete('*', function (req, res) {
doCRUD('DELETE',req,res);
res.end();
});
// expose this express app as a webtask-compatible function*/
module.exports = wt.fromExpress(app);
This error appears if you do not specify a valid path.
Try this one for example :
https://wt-666ohgod666ohgod666ohgod666ohgod-0.run.webtask.io/antidisestablishmentarianism666

how do i show ionic loading until local storage is populated in pouch

I have used service for storing data in local storage using pouchDB. I would like to show ionic loading until the data are downloaded and stored locally. For now I have used timeout which is not an option for me.
My Service
function populateLocaldb() {
var count;
_localdb.info().then(function(d){
console.log(d.doc_count)
count = d.doc_count;
if(count===0) {
populateData1();
populateData2();
populateData3();
} else {
}
});
}
function populateChapter() {
$http.get('http://....').success(function(data) {
//console.log(data)
var values= data;
for(var i=0; i<values.length; i++) {
var value= {
_id: values[i].ID,
title: chapters[i].Title
}
_localdb.put(value, function callback(err, result) {
if (!err) {
console.log('Successfully posted a value!');
}
});
}
})
}
Controller
dbService.getAllinfo().then(function(data) {
if(data == ""){
//do nothing
//alert(" null Alert hello")
console.log(data)
$ionicLoading.show({
content: 'Loading',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
}).then(function() {
dbService.populateLocaldb();
});
} else {
//do nothing
}
})
$timeout(function () {
$ionicLoading.hide();
}, 50000);
It looks like you might need to call $scope.$apply() in the PouchDB callback. Also, another tip: instead of doing multiple put()s inside of a forEach(), it's more efficient in PouchDB to do a single bulkDocs() operation.

nightwatch custom command callback

I'm trying to create a custom command in nightwatch that runs a query on a Postgres database and returns the result. The query runs just fine and outputs the result to the console but then the execution of the test stops. I don't understand how callbacks work. How can I fix this custom command?
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
}
else {
console.log(result.rows.length);
db.end();
}
});
}
}),
function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
}
return this;
};
I had to wrap the database connection in a perform command to get this working. I'm not sure if this is the best way to handle the callback, but it works. Here's the updated version of the custom command:
exports.command = function(sql,callback) {
var self = this;
var pg = require('pg');
var cs = self.globals.testinfo.connectionString;
self.perform(function(self,done) {
pg.connect(cs,function(err,db,done) {
if(err) {
return console.error(err);
}
db.query(sql, function(err,result) {
done();
if(err) {
return console.error(err);
}
console.log(result.rows.length);
callback(result.rows[0]);
});
});
pg.end();
done();
});
};
Here's how I call the custom command in the test:
browser.myCustomCommand('select * from table limit 1;', function(row) {
browser.assert.deepEqual(row.column,'some value');
});
Can you try this:
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
var cb= function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
};
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
cb(false);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
cb(false);
}
else {
console.log(result.rows.length);
db.end();
cb(true);
}
});
}
}),
return this;
};
And in your test :
'test' : function(browser){
browser.yourCommandName(sql,function(result){
console.log(result); //if connect is good result would be true and false if fail to connect.
});
}
Ps: the result in callback can be as an object(contain rows or anything you want), instead of boolean only in this example.
And Nightwatch is used for end-to-end testing, it is not aimed for Database testing,i think you should find another framework to test database connection.

Using design documents in pouchDB with crypto-pouch

After testing pouchDB for my Ionic project, I tried to encrypt my data with crypto-pouch. But I have a problem with using design documents. I used the following code:
One of my design documents:
var allTypeOne = {
_id: '_design/all_TypeOne',
views: {
'alle_TypeOne': {
map: function (doc) {
if (doc.type === 'type_one') {
emit(doc._id);
}
}.toString()
}
}
};
For init my database:
function initDB() {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
return _db.crypto(password)
.then(function(){
return _db;
});
// add a design document
_db.put(allTypeOne).then(function (info) {
}).catch(function (err) {
}
}
To get all documents of type_one:
function getAllData {
if (!_data) {
return $q.when(_db.query('all_TypeOne', { include_docs: true}))
.then(function(docs) {
_data = docs.rows.map(function(row) {
return row.doc;
});
_db.changes({ live: true, since: 'now', include_docs: true})
.on('change', onDatabaseChange);
return _data;
});
} else {
return $q.when(_data);
}
}
This code works without using crypto-pouch well, but if I insert the _db.crypto(...) no data is shown in my list. Can anyone help me? Thanks in advance!
I'm guessing that your put is happening before the call to crypto has finished. Remember, javascript is asynchronous. So wait for the crypto call to finish before putting your design doc. And then use a callback to access your database after it's all finished. Something like the following:
function initDB(options) {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
_db.crypto(password)
.then(function(){
// add a design document
_db.put(allTypeOne).then(function (info) {
options.success(_db);
})
.catch(function (err) { console.error(err); options.error(err)})
.catch(function (err) { console.error(err); options.error(err);})
}
}
initDB({
success:function(db){
db.query....
}
)