meanjs app with multiple server layout - angularjs

I want to use multiple server layout on meanjs framework, but the problem is how I can attach some angular front-end view page to specific server layout, I have a special login page that have a different server layout how I can fix this.
how can angular know what server layout must be loaded for which angular state.
I add an other action in core controller:
module.exports = function(app) {
// Root routing
var core = require('../../app/controllers/core.server.controller');
app.route('/').get(core.index);
app.route('/accounts/').get(core.login);
};

As of now, we couldn't able to create two layouts from server side. they need to update their core modules and routing techniques to resolve this problem.
I tried once and i couldn't complete the process, The idea is to change layout from server side routing and call layout render function in meanjs
Add additional code in core.server.routes.js
'use strict';
module.exports = function(app) {
// Root routing
var core = require('../../app/controllers/core.server.controller');
app.route('/').get(core.index);
app.route('/admin').get(core.admin);
};
Add aditional export function in core.server.controller.js
'use strict';
/**
* Module dependencies.
*/
exports.index = function(req, res) {
res.render('index', {
user: req.user || null,
request: req
});
};
exports.admin = function(req, res) {
res.render('admin', {
user: req.user || null,
request: req
});
};
Add layouts in layout folder accordingly.This will help you create multiple layouts, but still there is a lot of routing problems will occour as i said above. If it is possible to fix it, this may work.
Thanks,

Related

Routing between Express and Angular in MEAN.JS

I ran into issues on calling a Express route from my Angular template route and Express -> Angular. This code shows my attempt into tackling this issue.
// Server.js file, the main Node.js code
var Outlook = require('Outlook');
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
etc..
});
// Init the express application
var app = require('./config/express')(db);
app.listen('8443'); // Main server.
// App.js - The Outlook module Express route example code
var app = require('express');
var app = express();
// Configure express
// Set up rendering of static files
app.use(express.static('static'));
// Need JSON body parser for most API responses
app.use(bodyParser.json());
// Set up cookies and sessions to save tokens
app.use(cookieParser());
// Home page
app.get('/', function(req, res) {
res.send(pages.loginPage(authHelper.getAuthUrl()));
});
app.get('/express', function(req, res) {
console.log(req.params.msg);
return 'Your EXPRESS DATA IS HERE!';
});
app.listen(3000); // Is this really necessary?
// outlook.cliet.routes.js
'use strict';
//Setting up route
angular.module('outlook').config(['$stateProvider', '$http',
function($http) {
$http.get('http://localhost:3000/express',{"msg":"hi"}).success(function(data){
console.log(data);
});
]);
Issue 1: I don't want to make express run two different servers in different ports in the same instance. That lead me to next issue.
I am using oauth-sign and simple-oauth2 when I bounce back from the outlook module to the main express server, I am logged off the main server.
I don't think it is required a separate express server. Is it possible to make app.js express routing work without listening to a second express server? Notice that express is initialized in a different way. Perhaps module.exports could help?
Thanks

How to force login in angular full stack yeoman?

Is there a way to force the user to log in first in an app generated by the angular full stack yeoman ?
I tried to add the following code in the run part of app.js but was not successful
Auth.isLoggedIn(function(loggedIn) {
console.log(loggedIn);
if (!loggedIn) {
console.log("redirecting");
// event.preventDefault();
$state.go('login');
}
});
I found authentication controls in api index.js files but none for the / landing page ...
Thx
I did not use google as i should have !
To force authentication for a state, just add
authenticate: true
in the state (or all states in my case)
Without more code or information on which router you are using (generator-angular-fullstack supports both the default NgRouter and UIRouter) it is tough to give a complete answer. By your answer to your question I am assuming you have UI Router and have figured out how to do client side authentication within the generated fullstack code. However, you will also need to implement something similar to what they have done in their 'users' api to protect your api end points on the server side and return a 401/403 error.
'use strict';
var express = require('express');
var controller = require('./user.controller');
var config = require('../../config/environment');
var auth = require('../../auth/auth.service');
var router = express.Router();
router.get('/', auth.hasRole('admin'), controller.index);
router.delete('/:id', auth.hasRole('admin'), controller.destroy);
router.get('/me', auth.isAuthenticated(), controller.me);
router.put('/:id/password', auth.isAuthenticated(), controller.changePassword);
router.get('/:id', auth.isAuthenticated(), controller.show);
router.post('/', controller.create);
module.exports = router;
In the above code (which can be found by navigating to the server folder, then the api folder, then the user folder and looking at index.js) you will see that they are calling a couple of functions.
They are calling auth.hasRole('admin') and auth.isAuthenticated().
Those are functions which can be found in the server side auth/role service under the folder auth and in the auth.service.js file.
function hasRole(roleRequired) {
if (!roleRequired) throw new Error('Required role needs to be set');
return compose()
.use(isAuthenticated())
.use(function meetsRequirements(req, res, next) {
if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {
next();
}
else {
res.status(403).send('Forbidden');
}
});
}
I think it is important to understand how this is working on the server side also. So, if you navigate to localhost:9000/admin and open console you will see that there is a 401 or 403 error depending on whether or not you are logged in and/or logged in as an admin user.
Just Paste authenticate:true on main.js
angular.module('testcesarApp')
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/main/main.html',
controller: 'MainCtrl',
authenticate:true
});
});

How to enable HTML5 mode in Express without breaking NodeMailer?

everyone. I'm making my first Node + Express + Angular app.
I kinda used https://github.com/codeschool/StayingSharpWithAngularSTB as a boiler plate.
The general layout is
[folder] app
--------- [Sub-Folder] Assets (Javascript, css, images etc.)
--------- [Sub-Folder] Pages (This contains ng-view stuff)
--------- [Sub-Folder] Views
-------------------- index.html (This is the main index.html that holds everything together)
[folder] node_modules
[folder] server
--------- [Sub-Folder] Controllers
---------------------- core.server.controller.js
--------- expressConfig.js
--------- routes.js
app.js
package.json
So here's the my server configuring files:
app.js
var app = require("./server/routes");
// Start the server
var port = process.env.PORT || 8000;
app.listen(port, function(){
console.log('Listening on port ' + port);
});
/server/expressConfig.js
var bodyParser = require('body-parser');
module.exports = function(app, express) {
// Serve static assets from the app folder. This enables things like javascript
// and stylesheets to be loaded as expected. You would normally use something like
// nginx for this, but this makes for a simpler demo app to just let express do it.
app.use("/", express.static("app/"));
// Set the view directory, this enables us to use the .render method inside routes
app.set('views', __dirname + '/../app/views');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
};
/server/routes.js
var express = require('express');
var app = express();
var core = require('./controllers/core.server.controller')
// Load Express Configuration
require('./expressConfig')(app, express);
// Root route
app.get('/', function(req, res){
res.sendfile('index.html', {root: app.settings.views});
});
// routes for sending forms
app.route('/contact-form').post(core.sendMail);
app.route('/table-form').post(core.sendTableRes);
app.route('/artist-form').post(core.sendArtistRes);
module.exports = app;
/server/controllers/core.server.controller.js
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: //my gmail,
pass: //my gmail password
}
});
// Send an email when the volunteer form is submitted
exports.sendMail = function (req, res){
var data = req.body;
transporter.sendMail({
from: //my gmail,
to: //another gmail,
subject: data.volunteerName+ ' wants to volunteer for our event 2016',
text: 'Volunteer Info \n Name : '+data.volunteerName+'\n Phone Number : '
+data.volunteerNum+'\n E-mail : ' +data.volunteerEmail
});
res.json(data);
};
// Other similar mailing functions
And here's one of the angular controllers that sends the mail
volunteerFormController.js
angular.module('MyApp').controller('FormController', function($http){
this.volunteer = {
};
this.addVolunteer = function(){
var data = ({
volunteerName : this.volunteer.name,
volunteerEmail : this.volunteer.email,
volunteerNum : this.volunteer.phone
});
$http.post('/contact-form', data).
then(function(response) {
//show thank you message with animate.css classes and hide form
$(".thanksFriend").addClass("animated tada showBlock");
$("form").addClass("flipOutX animated hideBlock");
}, function(response) {
$(".sorryFriend").addClass("animated tada showBlock");
});
};
});
And this works just fine! But if I enable html5 mode in Angular and serve up the index in Express using
app.use(function(req, res){
res.sendfile('index.html', {root: app.settings.views});
});
in the routes.js file, Html 5 mode works great! No 404s when I remove the pound and refresh but then the none of my contact forms work, and the console isn't giving me any errors... My server files are pretty small and it's not super complicated so it should be pretty easy to figure out how to have both HTML5 mode AND working contact forms. Any ideas? I don't know much about Express and I used a tutorial http://www.bossable.com/1910/angularjs-nodemailer-contact-form/ to figure out how to use nodemailer. Is there another way to set up nodemailer so this works?
I would REALLY appreciate some help with this. It's driving me absolutely crazy ;__;
So, you had to serve every request return index.html,
by changing app.get('/', to app.get('/*',

NavBar address loading angular template but not root shell

I am using Node.JS with Express, Angular.JS and the node module connect-roles for ACL. I want to allow a user with user.status of "Platinum" to access "Platinum" but not "Gold" and vice versa.
I have the ACL part working, if I enter /Platinum into the navigation bar I can't access /Gold, but when I try to access /Platinum I only get the template but not the root shell, so what comes up is this:
You made it!
You have the {{status}} status!
If I click on a link in angular to /Platinum, everything works as it should. If I enter any neutral address in the navigation bar, everything works as it should.
This should be an easy fix, but I've not figured it out.
Here is the code that sets up authorizations, I'm pretty sure everything here is okay.
ConnectRoles = require('connect-roles')
var user = new ConnectRoles({
failureHandler: function(req, res, action){
var accept = req.headers.accept || '';
res.status(403);
if(accept.indexOf('html')) {
res.render('access-denied', {action: action});
} else {
res.send('Access Denied - You don\'t have permission to: ' + action);
}
}
});
var app = express();
app.use(user.middleware());
// Setting up user authorizations,
// i.e. if req.user.status = "Platinum", they are given Platinum status
user.use('Platinum', function(req) {
if (req.user.status == 'Platinum') {
return true;
}
});
user.use('Gold', function(req) {
if (req.user.status == 'Gold') {
return true;
}
});
user.use('Admin', function(req) {
if (req.user.status == 'Admin') {
return true;
}
});
That sets up authorizations, now the problem lies below with the routing.
app.post('/login', passport.authenticate('local',
{ successRedirect: '/', failureRedirect: '/login' }));
app.get('/Platinum', user.is('Platinum'), function(req, res) {
//Obviously the code below is wrong.
res.render('templates/support/Platinum');
});
app.get('/Gold', user.is('Gold'), function(req, res) {
res.render('templates/support/Gold');
});
The way you are configuring your routes on server side (using express) is not correct. For a single page app like AngularJS, you need to do all of the routing for pages on the client (i.e. in Angular). The server still defines routes for API requests (e.g. getting and posting data) and static resources (index.html, partial HTML files, images, javascript, fonts, etc), though.
Thus the following code is wrong in your server side JS:
app.get('/Platinum', user.is('Platinum'), function(req, res) {
//Obviously the code below is wrong.
res.render('templates/support/Platinum');
});
app.get('/Gold', user.is('Gold'), function(req, res) {
res.render('templates/support/Gold');
});
Just remove those lines.
Instead, you need to define the routes that the server will handle, such as your /login post one first, and how to get static files (I suggest prefixing them all with /pub in the URL). Then you need to do something like the technique in this answer to return your index.html page if no routes are matched.
That way, when a user types http://localhost:port/Gold, express will see there is no route defined for /Gold, so it will return index.html, which will load AngularJS, run your Angular app, which will then look at the URL and see if that matches any of the routes your AngularJS app has configured, and if so, fetch the partial for that page and insert it into your ng-view (if using the core router).

I am using MEAN.IO stack, why can't I hit my data-access layer using require?

So, I am using mean.io and for some reason, my routes.js never hits my 'index.all' method, or the 'exports.all' function, even though I require the functions from the server-side controller. Also, my routing is done using angular-ui-router. Does anybody know how to call a backend method from routing in MEAN.IO? I keep using:
'use strict';
module.exports = function(System, app, auth, database) {
// Home route
var index = require('../controllers/index');
app.route('/test').get(index.all);
app.route('/')
.get(index.render);
};
I would like to hit 'index.all' but even if I navigate to /test, it still gets
index.render. Does anybody know why?
Here is the controllers file:
'use strict';
var mean = require('meanio');
var mongoose = require('mongoose');
var Composition = mongoose.model('Composition');
exports.render = function(req, res) {
console.log(req.user);
var modules = [];
// Preparing angular modules list with dependencies
for (var name in mean.modules) {
modules.push({
name: name,
module: 'mean.' + name,
angularDependencies: mean.modules[name].angularDependencies
});
}
function isAdmin() {
return req.user && req.user.roles.indexOf('admin') !== -1;
}
// Send some basic starting info to the view
res.render('index', {
user: req.user ? {
name: req.user.name,
_id: req.user._id,
username: req.user.username,
roles: req.user.roles
} : {},
modules: modules,
isAdmin: isAdmin,
adminEnabled: isAdmin() && mean.moduleEnabled('mean-admin')
});
};
exports.all = function(req, res) {
console.log(req.user);
Composition.find({user: req.user}, 'title description').sort('-created').populate('user', 'name username').exec(function(err, compositions) {
if (err) {
return res.jsonp(500, {
error: 'Cannot list the compositions'
});
}
res.jsonp(compositions);
});
};
Is this a front-end or backend problem? Thanks for any advice that might be helpful.
You are navigating. So are you hitting the link in the browser url? Then you should try localhost:3000/test instead of localhost:3000/#!/test.
The urls of the form localhost:3000:/#!/<something> are angular routes. Look up angular routing and views. It is better to use angular views than server side rendering. Do angular routing for test and add a view corresponding to it. Fetch the dynamic data in the view using the regular $http.get calls.
Check this tutorial for routing and adding views in angular

Resources