Node.js and angular user authorization - javascript

How can i block request in node.js for HTML files when user was not authorized. I have html tree something like this:
app.use('/templates', express.static(path.join(__dirname, 'templates')));
index.html (for all)
panel.html (only for authorized)
settings.html (only for authorized)
Is any good and clearcode solutions for block this content ?? I think about something like this:
router.get('/templates/panel.html', function(req, res, next) {
if (req.session && req.session.user) {
// return content
} else {
// block content or send error.html
}
});
My ng-router config:
when('/panel', {
templateUrl: 'templates/panel.html',
controller: 'panelController',
// maybe controls authorize here to
}).
But what will happen when we use $templateCache?

Assuming you don't want other users to access some information, not to hide html templates.
Probably the best way would be to compile all your templates to $templateCache. Then inside your routing you could use the resolve property read here that:
An optional map of dependencies which should be injected into the
controller. If any of these dependencies are promises, the router will
wait for them all to be resolved or one to be rejected before the
controller is instantiated. If all the promises are resolved
successfully, the values of the resolved promises are injected and
$routeChangeSuccess event is fired. If any of the promises are
rejected the $routeChangeError event is fired. For easier access to
the resolved dependencies from the template, the resolve map will be
available on the scope of the route, under $resolve (by default) or a
custom name specified by the resolveAs property (see below). This can
be particularly useful, when working with components as route
templates.
this would allow you to do requests to server side where you will check for user privileges to open desired page.
Plus you would like to have some kind of authorization check on the server side when serving information for those pages-that-need-special-privileges.
It is also good idea to namespace your resources so authorization can be done easier and in 1 place.

Related

calling a function itself in a controller sails js

I know this same question has been asked before but the previous questions were in different languages and on different frameworks, and I tried all the methods mentioned in previous questions' answers but found no luck.
so here it is again.
I have a controller in my sails js app named orderController
code is:
module.exports = {
order_history: async function(req, res){
//get a response from an API and it is saved in nData
if(nData.status_code == 0 && nData.result == 'succeed'){
res.ok(nData.data);
}else{
updateCredentials();
order_history(req, res);
}
},
};
now if there are expired credentials then it updates the credentials and I want it to repeat itself so it can return the proper response in case of expired credentials. I do not want another request to be sent for this.
My advice would be to create a helper with the logic for order_history that you call from within the controller. If it fails, you can do the update_credentials, then call it again. I say this because sails is built with the idea that a controller's purpose is to be a specific response to a specific request endpoint and not meant to be reusable code. That's where the helper comes in, it's purpose is to be a globally available function. The benefit of doing it this way is that you won't end up in a situation where the order-history fails for a reason other than needing to update credentials, calls itself, fails for that reason again, updates credentials, calls itself... You can have it try updating credentials, then if it fails again respond with an error message.

Get templateUrl from ui-router

Maybe the title isn't really clear.
I'm working on two nested Angular apps. Both have their own router built with ui-router. If I call a state that is unknown by the main router, I'd like it to search for this state in the sub-app router to get the templateUrl and url related to this state.
I thought about creating a service with a parser. It could parse the file to find the data I want. This solution is probably not the best option I have, that's why I wanted to know if there is a specific function/method in ui-router to achieve it. From what I read on ui-router doc, it seems not :/
Feel free to ask for more details or to suggest another solution which can match with my goal :)
You can achieve this by using dynamic parameters in your $stateProvider configuration defined on your sub-module. So you have some anchored routes on the main module, and if there is a match, ui-router will simply fetch the associated template. If there is no matched absolute route/url, then ui-router falls back on your parameterised route, like so:
// anchored
$stateProvider
.state('mainAppState', {
url: '/anchored',
controller: 'myCtrl'
})
// sub module
.state('subAppState', {
url: /:parameter
resolve: { // use the resolve and $stateParams to get some parameter with which you can make a request to your API }
templateProvider: { // inject a service and use it to call your backend }
You can use a the parameter, which gets passed to $stateParams, which gets passed to your resolve block functions, which can retrieve some data or process the data from $stateParams, that can then be used by templateProvider to provide a meaningful fallback URL. That's because templateProvider receives all resolves. It will always wait for all promises in the resolve block to resolve one way or another before executing.
That way you can catch any unmatched URLs from the main app in your sub app. Hope this helps.
See my issue here: ui-router: async data in templateUrl function
Oh and one more thing - if you are going to mangle your JS in your build process, make sure you define your templateProvider function with .$inject = [ ... ]. If not, you'll get an unknown provider error. ngAnnotate will NOT catch the dependencies in your templateProvider function. Alternatively you can just use /* #ngInject */, which worked for me.

Run controllers only after initialization is complete in AngularJS

I have some global data that needs to be loaded before any controller is executed in my AngularJS application (i.e. resolve dependencies globally in AngularJS).
For example, I have a UserService with the getCurrentUser() method which does a request to the backend server in order to get data about the currently authenticated user. And I have a controller that needs this data in order to launch yet another request (for example to load user's balance).
How can I achieve that?
Update
Please consider using method specified in the «Asynchronously Bootstrapping AngularJS Applications with Server-Side Data» article if possible.
You can use the angular-deferred-bootstrap module to achieve that now!
I'm not sure about validity of this answer anymore, you can still use the ideas, but be sure to properly test it with your actual code. I will try to keep this answer up to date with never technologies.
Old answer
There are several approaches to the problem of asynchronous application initialization.
When it comes to data that must be resolved before a single controller is called - you can easily use resolve option of ngRoute's $routeProvider. However, when you need some global data to be loaded before ANY controller is called - you have to improvise.
I've tried to collect all possible solutions in this answer. I'm providing them in the order of preference.
1. Using ui-router
When using ui-router instead of native ngRoute you can create an abstract root state and resolve all data in it, before sub-states are activated.
I would recommend to use this approach. ui-router provides a lot of additional features including ability to resolve dependencies hierarchically and is well accepted by the developer community.
Example
module.config(function($urlRouterProvider, stateHelperProvider) {
$urlRouterProvider.otherwise('/404');
stateHelperProvider.setNestedState({
name: 'root',
template: '<ui-view/>',
abstract: true,
resolve: {
user: function(UserService) {
// getCurrentUser() returns promise that will be resolved
// by ui-router before nested states are activated.
return UserService.getCurrentUser();
}
},
children: [{
name: 'index',
url: '/',
templateUrl: '/partials/index'
}, {
name: 'not-found',
url: '/404',
templateUrl: '/partials/404'
}, {
name: 'balance',
url: '/balance',
templateUrl: '/partials/balance',
resolve: {
balance: function(UserService, user) {
// Using data resolved in parent state.
return UserService.getBalanceByAccountId(user.accountId);
}
}
}]
});
});
The stateHelper will help greatly to reduce the code when using abstract root scope approach.
Root scope is defined as abstract so can not be activated directly and it has no URL.
template: '<ui-view/>' is required for nested views to be properly rendered.
2. Making promises in root controller
You can make promises and add them to the $rootScope inside of your root controller, i.e. run() function.
I've created a Plunk to demonstrate the idea:
http://plnkr.co/edit/gpguG5Y2S4KOz1KOKzXe?p=preview
This is a perfectly working solution, however, it bloats the code and makes it harder to use and understand (callback hell). I would recommend it only if the first approach is not working for you.
3. Passing data with the application page
You can include all initialization data directly to the HTML page generated on the server and access it from your application.
Consider this example:
<html>
<body>
<script src="application.js"></script>
<script type="text/javascript">
application.init({
// Pass your data here.
userData: { ... }
});
</script>
</body>
</html>
And you can bootstrap AngularJS application manually in the init() method of your custom application object.
I don't really like this approach, as I do believe that frontend and backend of Web application should be highly separated. Ideally, your frontend should be a static website (e.g. bunch of HTML, CSS and JS that can be delivered via CDN) and your backend should be a strictly an API server without a presentation layer (i.e. it should know nothing about HTML, CSS and such). However, it's a working solution if you can live with tight integration between application components.

Angular bootstrap lifecycle: Run code after full load

Angular defines a run() block for an application module. This runs after config() and before any controllers and directives are loaded.
Is there a step in the lifecycle to run something after all controllers, directives, services, etc are loaded?
I need this in order to broadcast a message in my authorization pubsub service, and I want to ensure that everything is loaded before I publish the message. While I can check authentication in the run block (basically, just checking localstorage for a JWT via my authentication service), if I publish in the run() block I can't be sure if everything has loaded. I'm wondering if Angular exposes anything like this or whether I need to find a different solution.
Thanks!
An optional answer, taken from here
You can use a custom postDigest callback. if you need only the first postDigest callback, add a flag to indicate it happened
function postDigest(callback){
var unregister = $rootScope.$watch(function(){
unregister();
$timeout(function(){
callback();
postDigest(callback);
},0,false);
});
}
postDigest(function(){
console.log('do something');
})

Reject Angularjs resource promises

So I'm working on a Angularjs based mobile app. When a user taps on each of the tabs along the bottom a new route is called which is loading the partial and controller.
In my controllers I often then request data from the server via Angularjs $resource such as
$rootScope.getPage = pageApi.query(); // GET
$rootScope.getPage = $rootScope.getPage.$promise.then(function(data) {
//Do stuff with the returned data
});
I'm using root scope here because I have a spinning loader located outside of the controllers own $scope. While waiting for the response I'm using an Angular directive (Angular Busy) to display a loader.
However as the user moves through the pages on the app, more and more promises are started (that, for example, might not be resolved as the connection has been lost).
How can I resolve / reject any other promises so that only the most recently loaded controller is waiting on a promise ?
All comments / answers are really appreciated!
Thanks,
Mac

Categories

Resources