Where to put custom advanced queries in a sailsjs mongodb stack - mongodb

I want to proceed with more advanced queries in a sailsjs and mongodb stack where sailsjs is setup to serve as an api with data against a front end client. I've been able to fetch data with some basic queries but now looking into on how to proceed with more advanced ones. For example, I want to query the database for entries where the string match either the title or the text, something like this,
db.mycol.find({$or:[{"text":/.*test.*/},{"title": /.*test.*/}]})
My question, where do I put this logic? Any hints, links, tutorial that could point me into the right direction for this would be appreciated.

If you generate an api, for example:
sails generate api Customer
Sails will create a CustomerController for you in api>controllers.
You can add whatever custom endpoints you want to that.
If I put in CustomerController
blah: function(req, res) {
res.json(200, 'You are at blah');
}
and I navigate to customer/blah, it will hit that endpoint. So you can add whatever custom endpoints you want to for that controller. Go crazy.
Do not forget that sails has policy enforcement that you need to set up in the config/policies.js. This lets you expose, block, or add whatever middleware you need to in order to keep your back end as secure or open as it needs to be.

Related

Wrap findOne in sails.js User controller to make findMe

I'd like to create a new endpoint "/user/me" to call an action on my User controller called findMe(req, res). I'd like it to behave almost identically to the blueprint "/user/:id" which routes to findOne(req, res), except it will return the current user's data based on the logged in user's id (which is stored in req.session after login).
Is there an easy way to write findMe so it can pass the user ID to findOne and leave all the remaining request processing to the core sails findOne action?
I'm keen not to work with the findOne methods on User model directly but rather, use findOne on the User controller because it has added benefits, like honouring the ?polulate=... parameter, etc. That's said, tell me if this is a bad idea. I'm slightly concerned about the security implications - could s malicious user get to other users data via a forged /user/me request?
In other environments I've known this as server side redirects (different to client side redirects / 30x).
Thanks
Adam
You can totally access the blueprints from a controller. This is how you would do it if you store the user id inside the session as req.session.user.id:
// UserController.js
module.exports = {
me: function (req, res) {
req.params.id = req.session.user.id;
return sails.hooks.blueprints.middleware.findone(req, res);
}
};
However, this would not allow you to use other params such as populate.
I personally think you should implement your own action as it won't be really complicated and will be easier to secure the requests.

Breeze EFContextProvider per request and based on parameter?

I have a multi-tenant app in which user can select "current company" after they log in.
There is a DB per company but the model is the same, the workflow is the same, and the controller actions are same....The user can switch companies while being logged in and all actions need to be 'directed' to proper DB.
I know it is possible to customize context creation in EFContextProvider<T> by overriding CreateContext() but how do I pass the extra info (parameter, e.g. CompanyId) that would allow me to create context with correct connection string?
Is this possible?
I find the easiest way is to include the tenant id in a custom HTTP header.
Because the tenant id changes during the session, you probably want to create a custom Breeze ajax adapter (wrap the one you're using now) that sets this header dynamically during its implementation of the ajax method.
On the server you fish the header out of the request.
MAKE SURE YOU ARE VALIDATING USER AND HEADER ON THE SERVER

Using Everyauth/Express and Multiple Configurations?

I'm successfully using Node.js + Express + Everyauth ( https://github.com/abelmartin/Express-And-Everyauth/blob/master/app.js ) to login to Facebook, Twitter, etc. from my application.
The problem I'm trying to wrap my head around is that Everyauth seems to be "configure and forget." I set up a single everyauth object and configure it to act as middleware for express, and then forget about it. For example, if I want to create a mobile Facebook login I do:
var app = express.createServer();
everyauth.facebook
.appId('AAAA')
.appSecret('BBBB')
.entryPath('/login/facebook')
.callbackPath('/callback/facebook')
.mobile(true); // mobile!
app.use(everyauth.middleware());
everyauth.helpExpress(app);
app.listen(8000);
Here's the problem:
Both mobile and non-mobile clients will connect to my server, and I don't know which is connecting until the connection is made. Even worse, I need to support multiple Facebook app IDs (and, again, I don't know which one I will want to use until the client connects and I partially parse the input). Because everyauth is a singleton which in configured once, I cannot see how to make these changes to the configuration based upon the request that is made.
What it seems like is that I need to create some sort of middleware which acts before the everyauth middleware to configure the everyauth object, such that everyauth subsequently uses the correct appId/appSecret/mobile parameters. I have no clue how to go about this...
Suggestions?
Here's the best idea I have so far, though it seems terrible:
Create an everyauth object for every possible configuration using a different entryPath for each...
Apparently I jumped the gun and wrote this before my morning cup of coffee, because I answered my own question, and it was quite easy to implement. Basically I just had to create my own custom express middleware to switch the everyauth configuration before the everyauth gets its grubby paws on the request, so...
var configureEveryauth = function()
{
return function configure(req, res, next) {
// make some changes to the everyauth object as needed....
next();
};
}
and now my setup becomes:
var app = express.createServer();
everyauth.facebook
.entryPath('/login/facebook')
.callbackPath('/callback/facebook');
app.use(configureEveryauth());
app.use(everyauth.middleware());
everyauth.helpExpress(app);
app.listen(8000);
Notice that I don't even bother fully configuring the everyauth Facebook object during the startup, since I know that the middleware will fill in the missing params.

How is ACL implemented

i am using Zend_Acl, PHP and is wondering how shld ACLs be implemented.
shld every page be a resource and i always query the acl to see if a user is authorized? i guess i must use this if i want to use a controller plugin (can be setup to run on every request) to check if a user is allowed?
or do i just put the query code where i need it? eg. at the top of pages i need to query the acl? then in pages publicly available, i just skip it? may get troublesome if the application gets big?
ok, i just answer this question then close it
what i did now was have a controller plugin that sets its resource based on controller name and privilege based on action name. then query the acl based on that
still under development, but what i currently have look like http://pastebin.com/9BYzms7W

Need help with Zend Framework dynamic Namespaces

I want to make my system redirect unknown requests such as
www.address.com/a_company
to the adress
www.address.com/companies/company/ and display the company a_company if it exists in the database, otherwise throw the user to a 404 not found page.
So in detail, I want to make namespace that is as the first example dynamically, if the company exist in the database, I have no problem connecting to the database and retrieving information or finding a way to parse a company name, I just need help how to make my system check and run a function every time the address doesn't exist and show the second page (/companies/company/)..
I am using an Acl as well, but I think it should be fine if the page is /companies/company and then possibly add /?c=a_company or similar.
Thank you.
/Marcus
simply create a front controller plugin which checks the request params agains the database before the request is dispatched.