Sails.js - use login instead of id for REST api - node.js

I'm using Sails.js framework, and I have User model with login field.
I also have User controller that allows me to send request like
http://localhost:1337/user/:id
And it returns given user data. However I'd prefer to use user login instead of user id so I could use /user/mylogin instead of /user/564a0aacecf0e8fb20c38a4e. Is there any way to do it without creating routes myself (I like how sails handle all default routes including relations like /user/:id/comments and I dont want to rebuild all of those just to use login instead of id)

You could do /user?login=username. This is handled by sails's blueprint api: http://sailsjs.org/documentation/reference/blueprint-api/find-where

If you really want it you can have it. But you have to get your hands a bit dirty. There are a few possibe ways. But I am pointing you out the easiest way seemed to me.
Add a route like following in your config/routes.js.
'/user/:myLogin': {
controller: 'user',
action:'getUserByUserLogin'
}
Add an action named getUserByUserLogin in your
api/controller/UserController.js. You can access the myLogin
value from request object from the controller action with
req.param("myLogin").
module.exports = {
getUserByUserLogin: function(req, res){
var myLogin = req.param("myLogin");
/* Do whatever you want */
}
};

Related

Show public logic if user is not authenticated React JS and Node API

How can I show only public(i.e: home, about, authentication stuff) if the user is not signed in?
I know SPA's are not meant to refresh, but I want it to change most of the scripts on the page.
Environment: Using ReactJS, WebPack with an existing NodeJS API, both on separate projects.
I went through Webpack documentation and understood that it will load only the required scripts and components, but all scripts can be seen with "View Page Source". If I understood it the wrong way, please correct me.
Ideally you track if the user is logged-in or not by storing a sessiontoken somewhere in your application state tree. You can use something like Redux to manage state in your application. You first need to decide which route you need to redirect to if the user is not logged-in & requests a route which requires authentication. Lets assume you have 2 routes /login and /products. You want to ensure that only authenticated users can view the /products section. The way you accomplish this is by redirecting to /login by checking the sessiontoken value of your state which you can pass as props to your Products component mapped to the /products route.
Use something like react-router
In the Products component use something like below
class Products extends Component{
componentWillUpdate(nextProps, nextState, nextContext) {
let {sessiontoken}=nextProps;
if (!sessiontoken)
nextContext.router.push('/login');
}
}
Products.contextTypes = {
router: React.PropTypes.object.isRequired
}
In the code above we are reading the value of sessiontoken which is passed as props from a higher order Container component. In case there is no sessiontoken it will redirect to /login. As long as your APIs return an HTTP 401 on encountering an invalid sessiontoken this will work perfectly for you and you don't need to worry about people being able to view page source.

KeyStone JS Account Controller

I understand MVC structure when coding in NodeJS. I started using Keystone JS recently, and I really like it. But, the way they set their controllers up, it seems that the controllers ONLY serve the purpose of rendering a view.
In an earlier project, I had an Account.js model and an Account.js controller. I'm trying to see how it would copy over to keystone.
So: How would I allow users to signup/signin/logout in a Keystone project (not into the Admin UI, but like a member of a regular site)? How would I make an Account controller (obviously with no view to render)?
There are lots of ways you can implement your own methods of authentication and account management in keystone since it is based on express.js.
You can then add an array of 'middleware' functions to routes which will run before passing the request to the controller.
e.g
Route before middleware added
app.get('/admin', routes.views.userAdmin);
Middleware Function
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
Route with middleware added
app.get('/admin', isAuthenticated, routes.views.userAdmin);
It's a very broad questions so I'd recommend you go and decide on the best way you'd like to do it yourself as everyone has their own personal preference. The search terms you want are 'express middleware authentication'. A lot of people use PassporJS http://passportjs.org/
Hope that helps :)

How can a Sails controller get request history

I am developing a website using Nodejs (with Sails & Passport frameworks). I am wondering how a Sails controller get the request history of a user.
For instance, a user requests for '/', but a controller redirects the user to '/signin'. Then the user requests for '/signin' using res.redirect(). So the request history looks like
'/'
'/signin'.
Now a SignInController handles the request and at the end, it want to redirect the user back to '/'. So the controller should know the history of the user's request. I guess there should be some frameworks which can record request histories and store them using session or something. Could anyone give me some hints about this?
Let me know if I understood well but what you want to do is to redirect the user to whatever URL he was before a login, right?
To do that you can use the policies (which are executed for all requests, only on the methods you want).
What we do here is save the latest position only (Not the entire history)
In api/policies/ensureReturnToUrl:
'use strict';
module.exports = function (req, res, next) {
req.session.returnTo = req.url;
return next();
};
The configuration part look like that in config/policies.js:
'*': ['passport', 'isAuthenticated', 'ensureReturnToUrl'],
AuthController: {
'*': ['passport']
}
You will have to be careful here to put this policy in the right place only. For example, you don't want to have it on you "/signin" methods (That goes against the whole point)
Then, after a successful login, you just have to read the "returnTo" property and redirect the user: (For example in a AuthController)
if (req.session.returnTo) {
res.redirect(req.session.returnTo);
} else {
res.redirect('/');
}
Obviously this need to be adapted for your use case but the policies are definitely what you need.

sails: how to redirect after creating a model with the built-in crud operations?

I'm dong some quick testing with the Sails framework for Node.
I like the way default CRUD-operations work out of the box, once a model and a controller (e.g.: for user ) are created.
I'm having a bit trouble with extending the basics though.
Say:
I've created a User-model and empty User-controller.
This should give me default Rest and Crud operations.
I've defined a user-signup form that does as POST to user/create. This functionality is defined out of the box.
This works, but results in displaying the created JSON at user/create.
How do I extend this to redirect to a certain url for example the user profile? (e.g.: GET user)
You will need your own controller method. It could be as simple as below.
create: function(req, res) {
User.create(req.body).exec(function(err, result){
if (err) {
//Handle Error
}
return res.redirect('/somewhere')
});
}

Accessing session variables in sailsjs view

I am quite new to sailsjs and nodejs. I am trying to create an authentication page, wherein once a user is authenticated, I want to set
req.session.user = user.id
req.session.authenticated = true
I then need to access these values within my main layout.ejs file. I have done so by using
res.locals.user = _.clone( req.session.user )
However, I noticed that this clone method has to be called in every function of every controller so as to allow me to be able to access the user from within the views. Is there a better way of accessing session variables in sailsjs globbaly, without having to clone the req.session in every controller. An example of what I am doing can be found here:
http://pastebin.com/HyE2H4Kq
As you can see, I have called the clone method at the beginning of various functions within the controller.
The req object is available in your views by default, unless you overwrite res.locals completely. So you can access a session variable in your view with <%=req.session.user%> (if you're using EJS). You don't have to copy it explicitly into your locals.
for anyone using passport.js, session of the user is saved inside req.session.passport.user and you also can access it directly from the view
I have finally decided to go with a solution provided here as I found this to be the neatest solution.
I have created a config file called userdata.config in which I have the following code:
module.exports.userdata = {
guest: true,
authenticated: false
};
I am then accessing this in the controller as follows:
sails.config.userdata.authenticated = true;
sails.config.userdata.guest = false;
sails.config.userdata.user = sessionUser;
This is then accessed in the view as follows:
sails.config.userdata.user.firstName

Resources