Non functioning default policy in SailsJS - sails.js

I'm trying to implement the basic Passport integration in SailsJS. In my policies.js file, I have the default settings that every tutorial mentions.
'*': ['passport', 'sessionAuth'],
'auth': {
'*': ['passport']
}
My issue is that going to the main page localhost:1337/ doesn't seem to get passed through either policy. If I just set false there, everything still works. If I set false on the auth object for '*' though, I will get Forbidden on any /auth/* route. So, the policies seem to work, I just don't understand why the default catch-all doesn't. Thanks.

Do you use a controller or do you directly serve a view like in the sample homepage?
If you are serving the view directly with something similar to this:
// in config/routes.js
module.exports.routes = {
'/': {
view: 'homepage'
}
}
then you will have to modify it and use a controller in order to te able to use policies.
Create a route to a controller instead of a view:
// in config/routes.js
module.exports.routes = {
// Delete the previous definition and declare a route
// to a controller "index"
'get /': 'indexController.home'
}
Create the controller:
// in api/controllers/IndexController.js
module.exports = {
home: function (req, res) {
// Render the view located in "views/homepage.ejs"
res.view('homepage');
}
};
Then you will be able to manage the policies to apply to the controller index in the file config/policies.js.

Related

in sails set controller as default route instead of view

in config/routes.js what happens when controller is needed instead of view
module.exports.routes = {
'/': {
view: 'index'
}
};
basically I want to load some data on the index page but I cant because there is no controller, in addition I want to have other pages like about, contact etc... but I prefer to put them to a PublicController instead of routes.js
If I get your question, may be you are looking for something this,
module.exports.routes = {
'/': {
controller: 'User',
action: 'actionName'
}
};
At first I didn't notice your comment. If you want to put all of those sections under different routes(like /about for about section) then there is no way to do it very simply.
But yes I have done it using React.js front end framework, where you can define routes in a single view file using React Routes. Defining in routes.js is not necessary. Rendering that single file from only one controller would enable you to use all those routes defined in that view file. Can't tell you any other way.
Hope it helps.
As your comments show you can specific the controller, action in your routes.
In your controllers you can specify the view to be rendered.
PublicController.js
module.exports = {
randomAction : function(req,res,next){
res.view('./randomActionViewFile');
}
}
Note this is unnecessary if the view file is already in the folder structure api/views/public/randaomActionFile.ext. Instead you can just use res.ok

SailsJS Policy based route with a view

I'm trying to use the routes.js to define a route to '/account'.
I want whoever is trying to access that path to go through the UserController and the checkLogin action and if the security check passes, then the user should be rendered with the defined view which is home/account
Here is my code:
routes.js:
'/account': {
controller: 'UserController',
action: 'checkLogin',
view: 'home/account'
}
policies.js:
UserController: {
'*': 'isAuthenticated',
'login': true,
'checkLogin': true
}
It let's me view /account without going through the isAuthenticated policy check for some reason.
There looks to be a little confusion here as to how policies, controllers and views work. As #bredikhin notes above, your controller will never be called because the route is being bound to a view. It's also important to note that policies cannot be bound to views, only to controllers. The correct setup should be something like:
In config/routes.js:
'/account': 'UserController.account'
In config/policies.js:
UserController: {
'*': 'isAuthenticated' // will run on all UserController actions
// or
'account': 'isAuthenticated' // will run just on account action
}
In api/policies/isAuthenticated.js:
module.exports = function(req, res, next) {
// Your auth code here, returning next() if auth passes, otherwise
// res.forbidden(), or throw error, or redirect, etc.
}
In api/controllers/UserController.js:
module.exports = {
account: function(req, res) {
res.view('home/account');
}
}
To put it short: either controller/action-style or view-style routing should be used within the same route in routes.js, not both simultaneously.
According to the router's source code, once there is a view property in a route object, binding stops, so basically Sails never knows to which controller your /account path should be routed, which means that your UserController-specific policy config never fires.
So, just remove the view property from the route, you can always specify the view path (if you want a non-standard one) with explicit rendering from within your action.
For statics work with policies, you can set your route with controller and action:
'GET /login': 'AuthController.index',
And set view/layout in your controller:
index: function (req, res) {
res.view('auth/login', { layout: 'path/layout' } );
},

Durandal routing issue

I have small SPA test app with Durandal.
Also I have very wired issue.
First, my folder structure is:
App
--durandal
--viewmodels
----user.js
--views
----user.html
--main.js
And when structure is like that all works just fine. But if I create structure like
App
--durandal
--_user
----viewmodels
------user.js
----views
------user.html
I get error like localhost/App/_users/viewmodels/users.html 404 Not Found. And that happens after user.js are loaded by require.js.
my main.js looks like
require.config({
paths: { "text": "../durandal/amd/text" }
});
define(function (require) {
var system = require('../durandal/system'),
app = require('../durandal/app'),
router = require('../durandal/plugins/router'),
viewLocator = require('../durandal/viewLocator'),
logger = require('../logger');
system.debug(true);
app.start().then(function () {
// route will use conventions for modules
// assuming viewmodels/views folder structure
router.useConvention();
// When finding a module, replace the viewmodel string
// with view to find it partner view.
// [viewmodel]s/sessions --> [view]s/sessions.html
// Otherwise you can pass paths for modules, views, partials
// Defaults to viewmodels/views/views.
viewLocator.useConvention();
app.setRoot('viewmodels/shell');
// override bad route behavior to write to
// console log and show error toast
router.handleInvalidRoute = function (route, params) {
logger.logError('No route found', route, 'main', true);
};
});
});
I assume that this issue has something with router.useConvention(); or with viewLocator.useConvention(); but simple can't find any reason for that kind of behavior.
Any help, suggestion, idea how to solve this?
Thanks
This is because of the behavior of the view locator, which by defaults looks for views/viewmodels in the first structure you describe.
You can easily change this behavior by supplying your own view locator function, or by calling useConvention() like this useConvention(modulesPath, viewsPath, areasPath)

How to create a simple landing page in MVC2

I'm trying to create a http://domain.com/NotAuthorized page.
went to Views\Shared and added a View called NotAuthorized witch originates the file name NotAuthorized.aspx
in my Routes I wrote
routes.MapRoute(
"NotAuthorized", // Route name
"NotAuthorized.aspx" // Route Url
);
but every time I access http://domain.com/NotAuthorized I get an error
The resource cannot be found.
What am I missing?
How can access this without using View("NotAuthorized") in the Controller, in other words, not passing through any controller.
You can't access views directly without passing through a controller. All pages in the Views folder cannot be served directly. So one way to accomplish what you are looking for is to write a custom[Authorize] attribute and set the error page:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "NotAuthorized" };
}
}
I still have no idea on how to accomplish it, but what I did was use the Home Controller and create an Action called NotAuthorized
public ActionResult NotAuthorized()
{
return View();
}
And add a route like
routes.MapRoute(
"NotAuthorized", // Route name
"NotAuthorized", // URL with parameters
new { controller = "Home", action = "NotAuthorized" } // Parameter defaults
);
And works fine now, I can easily redirect in any part of my Business Logic to /Notauthorized and that will route fine.

Custom route doesn't find controller action

For some reason my application isn't routing to my controller method correctly. I have a routelink like this in my webpage -
<%= Html.RouteLink("View", "Blog", new { id=(item.BlogId), slug=(item.Slug) }) %>
In global.asax.cs I have the following routes -
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"MoreBlogs",
"Blog/Page/{page}",
new { controller = "Blog", action = "Index" }
);
routes.MapRoute(
"Blog",
"Blog/View/{id}/{slug}",
new { controller = "Blog", action = "View"}
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
And then I have a class BlogController that has a method -
public ActionResult View(int id, string slug)
{
... etc.
}
I put a breakpoint in the first line of the View method but it's not getting hit at all. I checked with a route debugger for the format localhost/Blog/View/1/test and it matched my custom route. All I'm getting is a 404 while running this, I can't work out why the route won't post to the view method in my controller - any ideas?
(Assuming the route debugger was based on Phil Haack's debugger post)
If you're getting a 404, that makes me think the actual view page itself cannot be found.
Assuming that you are also using areas within the application, and that RouteLink is actually being called from within an Area, I think you may need to specify area="" in your routeValues object ( you also need to specify the controller). In general, I think that you will need to add the area="..." part with all your Routelink calls when using Areas.
This is something that I have picked up about RouteLink and Area, but cant seem to find any reference material detailing the limitations.