· 9 years ago · Apr 13, 2016, 01:00 PM
1/**
2 * Satellizer Node.js Example
3 * (c) 2015 Sahat Yalkabov
4 * License: MIT
5 */
6var formidable = require('formidable');
7var fs = require('fs');
8var mv = require('mv');
9
10var path = require('path');
11var qs = require('querystring');
12
13var async = require('async');
14var bcrypt = require('bcryptjs');
15var bodyParser = require('body-parser');
16var colors = require('colors');
17var cors = require('cors');
18var express = require('express');
19var logger = require('morgan');
20var jwt = require('jwt-simple');
21var moment = require('moment');
22var mongoose = require('mongoose');
23var request = require('request');
24
25var config = require('./config');
26
27var userSchema = new mongoose.Schema({
28 email: { type: String, unique: true, lowercase: true },
29 password: { type: String, select: false },
30 displayName: String,
31 level: Number,
32 picture: String,
33 facebook: String,
34 google: String,
35 twitter: String
36});
37
38var fileSchema = new mongoose.Schema({
39 nomefile: String,
40 directory: String,
41 dataupload: {type: Date, default: Date.now},
42 size: String,
43 type: String,
44}, {collection:'file'});
45
46var File = mongoose.model('File',fileSchema);
47
48userSchema.pre('save', function(next) {
49 var user = this;
50 if (!user.isModified('password')) {
51 return next();
52 }
53 bcrypt.genSalt(10, function(err, salt) {
54 bcrypt.hash(user.password, salt, function(err, hash) {
55 user.password = hash;
56 next();
57 });
58 });
59});
60
61userSchema.methods.comparePassword = function(password, done) {
62 bcrypt.compare(password, this.password, function(err, isMatch) {
63 done(err, isMatch);
64 });
65};
66
67var User = mongoose.model('User', userSchema);
68
69mongoose.connect(config.MONGO_URI);
70mongoose.connection.on('error', function(err) {
71 console.log('Error: Could not connect to MongoDB. Did you forget to run `mongod`?'.red);
72});
73
74var app = express();
75
76/* INCLUSIONE SOCKET.IO */
77var server = require('http').createServer(app);
78var io = require('socket.io')(server);
79
80
81app.set('port', process.env.PORT || 3000);
82app.use(cors());
83app.use(logger('dev'));
84app.use(bodyParser.json());
85app.use(bodyParser.urlencoded({ extended: true }));
86
87// Force HTTPS on Heroku
88if (app.get('env') === 'production') {
89 app.use(function(req, res, next) {
90 var protocol = req.get('x-forwarded-proto');
91 protocol == 'https' ? next() : res.redirect('https://' + req.hostname + req.url);
92 });
93}
94app.use(express.static(path.join(__dirname, '../client')));
95
96
97/*
98 |--------------------------------------------------------------------------
99 | Login Required Middleware
100 |--------------------------------------------------------------------------
101 */
102function ensureAuthenticated(req, res, next) {
103 if (!req.header('Authorization')) {
104 return res.status(401).send({ message: 'Please make sure your request has an Authorization header' });
105 }
106 var token = req.header('Authorization').split(' ')[1];
107
108 var payload = null;
109 try {
110 payload = jwt.decode(token, config.TOKEN_SECRET);
111 }
112 catch (err) {
113 return res.status(402).send({ message: err.message });
114 }
115
116 if (payload.exp <= moment().unix()) {
117 return res.status(402).send({ message: 'Token has expired' });
118 }
119 req.user = payload.sub;
120 next();
121}
122
123/*
124 |--------------------------------------------------------------------------
125 | Generate JSON Web Token
126 |--------------------------------------------------------------------------
127 */
128function createJWT(user) {
129 var payload = {
130 sub: user._id,
131 iat: moment().unix(),
132 exp: moment().add(14, 'days').unix(),
133 lev: user.level
134 };
135 return jwt.encode(payload, config.TOKEN_SECRET);
136}
137
138/* SEZIONE SOCKET IO */
139io.on('connection', function(socket){
140 socket.emit('news',{hello: 'world'});
141 socket.on('my other event',function(data){
142 console.log(data);
143 });
144});
145
146
147/*
148 |--------------------------------------------------------------------------
149 | GET /api/me
150 |--------------------------------------------------------------------------
151 */
152app.get('/api/me', ensureAuthenticated, function(req, res) {
153 User.findById(req.user, function(err, user) {
154 res.send(user);
155 });
156});
157
158
159app.get('/api/contactlist', ensureAuthenticated,
160 function(req,res){
161 User.find(function(err,user){
162 res.send(user);
163 });
164});
165
166
167app.delete('/api/removecontact/:id', ensureAuthenticated,
168 function(req,res){
169 var id = req.params.id;
170 User.remove({_id: id},function(err,user){
171 if (err){
172 console.log('Errore' + err);
173 }
174 res.send(user);
175 });
176});
177
178app.post('/api/upload', function(req,res){
179 var form = new formidable.IncomingForm();
180 var token = req.headers.authorization.split(' ')[1];
181 var payload = jwt.decode(token, config.TOKEN_SECRET);
182 var iduser = payload.sub;
183 form.parse(req,function(err,fields,files){
184 if (!err){
185 var file = files.file;
186 var tempPath=file.path;
187 var targetPath=path.resolve('./file/'+iduser+'/'+file.name);
188 var filedb = new File({
189 nomefile: file.name,
190 directory: iduser,
191 size: file.size,
192 type: file.type
193 });
194 filedb.save(function(err,data){
195 if (err){
196 console.log(err);
197 }
198 });
199 mv(tempPath,targetPath, {mkdirp: true}, function(err){
200 if (err) {
201 throw err;
202 }
203 return res.status(200).send('ok');
204 });
205 }
206 else {
207 console.log('there is an error in upload');
208 }
209
210 });
211});
212
213app.get('/api/readdir', function(req,res){
214 var basedir = './file/';
215 var token = req.headers.authorization.split(' ')[1];
216 var payload = jwt.decode(token, config.TOKEN_SECRET);
217 var iduser = payload.sub;
218 File.find({directory: iduser}, function(err,docs){
219 if (err){
220 console.log(err);
221 }
222 else {
223 return res.status(200).send(docs);
224 }
225 });
226});
227
228app.post('/api/downfile',function(req,res){
229 var id = req.body.id;
230 File.find({_id: id}, function(err,docs){
231 if (err){
232 console.log(err);
233 }
234 else {
235 var query=docs[0];
236 var path='./file/'+query.directory+'/'+query.nomefile;
237 var file = fs.readFileSync(path,'binary');
238 res.setHeader('Content-Length', file.length);
239 res.setHeader('Content-Disposition', 'attachment; filename="'+query.nomefile+'"');
240 res.setHeader('Content-Type', query.type);
241 res.write(file,'binary');
242 res.end();
243 }
244 });
245});
246
247
248/*
249 |--------------------------------------------------------------------------
250 | PUT /api/me
251 |--------------------------------------------------------------------------
252 */
253app.put('/api/me', ensureAuthenticated, function(req, res) {
254 User.findById(req.user, function(err, user) {
255 if (!user) {
256 return res.status(400).send({ message: 'User not found' });
257 }
258 user.displayName = req.body.displayName || user.displayName;
259 user.email = req.body.email || user.email;
260 user.save(function(err) {
261 res.status(200).end();
262 });
263 });
264});
265
266
267app.put('/api/updatelevel',ensureAuthenticated,function(req,res){
268 User.findById(req.body.id,function(err,user){
269 if (!user){
270 return res.status(400).send({message: 'User not found'});
271 }
272 user.level = req.body.level;
273 user.save(function(err){
274 res.status(200).end();
275 });
276 });
277});
278
279/*
280 |--------------------------------------------------------------------------
281 | Log in with Email
282 |--------------------------------------------------------------------------
283 */
284app.post('/auth/login', function(req, res) {
285 User.findOne({ email: req.body.email }, '+password', function(err, user) {
286 if (!user) {
287 return res.status(401).send({ message: 'Invalid email and/or password' });
288 }
289 user.comparePassword(req.body.password, function(err, isMatch) {
290 if (!isMatch) {
291 return res.status(401).send({ message: 'Invalid email and/or password' });
292 }
293 res.send({ token: createJWT(user) });
294 });
295 });
296});
297
298/*
299 |--------------------------------------------------------------------------
300 | Create Email and Password Account
301 |--------------------------------------------------------------------------
302 */
303app.post('/auth/signup', function(req, res) {
304 User.findOne({ email: req.body.email }, function(err, existingUser) {
305 if (existingUser) {
306 return res.status(409).send({ message: 'Email is already taken' });
307 }
308 var user = new User({
309 displayName: req.body.displayName,
310 email: req.body.email,
311 password: req.body.password,
312 level: '0'
313 });
314 user.save(function(err, result) {
315 if (err) {
316 res.status(500).send({ message: err.message });
317 }
318 res.send({ token: createJWT(result) });
319 });
320 });
321});
322
323/*
324 |--------------------------------------------------------------------------
325 | Login with Google
326 |--------------------------------------------------------------------------
327 */
328app.post('/auth/google', function(req, res) {
329 var accessTokenUrl = 'https://accounts.google.com/o/oauth2/token';
330 var peopleApiUrl = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect';
331 var params = {
332 code: req.body.code,
333 client_id: req.body.clientId,
334 client_secret: config.GOOGLE_SECRET,
335 redirect_uri: req.body.redirectUri,
336 grant_type: 'authorization_code'
337 };
338
339 // Step 1. Exchange authorization code for access token.
340 request.post(accessTokenUrl, { json: true, form: params }, function(err, response, token) {
341 var accessToken = token.access_token;
342 var headers = { Authorization: 'Bearer ' + accessToken };
343
344 // Step 2. Retrieve profile information about the current user.
345 request.get({ url: peopleApiUrl, headers: headers, json: true }, function(err, response, profile) {
346 if (profile.error) {
347 return res.status(500).send({message: profile.error.message});
348 }
349 // Step 3a. Link user accounts.
350 if (req.header('Authorization')) {
351 User.findOne({ google: profile.sub }, function(err, existingUser) {
352 if (existingUser) {
353 return res.status(409).send({ message: 'There is already a Google account that belongs to you' });
354 }
355 var token = req.header('Authorization').split(' ')[1];
356 var payload = jwt.decode(token, config.TOKEN_SECRET);
357 User.findById(payload.sub, function(err, user) {
358 if (!user) {
359 return res.status(400).send({ message: 'User not found' });
360 }
361 user.google = profile.sub;
362 user.picture = user.picture || profile.picture.replace('sz=50', 'sz=200');
363 user.displayName = user.displayName || profile.name;
364 user.save(function() {
365 var token = createJWT(user);
366 res.send({ token: token });
367 });
368 });
369 });
370 } else {
371 // Step 3b. Create a new user account or return an existing one.
372 User.findOne({ google: profile.sub }, function(err, existingUser) {
373 if (existingUser) {
374 return res.send({ token: createJWT(existingUser) });
375 }
376 var user = new User();
377 user.google = profile.sub;
378 user.picture = profile.picture.replace('sz=50', 'sz=200');
379 user.displayName = profile.name;
380 user.save(function(err) {
381 var token = createJWT(user);
382 res.send({ token: token });
383 });
384 });
385 }
386 });
387 });
388});
389
390/*
391 |--------------------------------------------------------------------------
392 | Login with Facebook
393 |--------------------------------------------------------------------------
394 */
395app.post('/auth/facebook', function(req, res) {
396 var fields = ['id', 'email', 'first_name', 'last_name', 'link', 'name'];
397 var accessTokenUrl = 'https://graph.facebook.com/v2.5/oauth/access_token';
398 var graphApiUrl = 'https://graph.facebook.com/v2.5/me?fields=' + fields.join(',');
399 var params = {
400 code: req.body.code,
401 client_id: req.body.clientId,
402 client_secret: config.FACEBOOK_SECRET,
403 redirect_uri: req.body.redirectUri
404 };
405
406 // Step 1. Exchange authorization code for access token.
407 request.get({ url: accessTokenUrl, qs: params, json: true }, function(err, response, accessToken) {
408 if (response.statusCode !== 200) {
409 return res.status(500).send({ message: accessToken.error.message });
410 }
411
412 // Step 2. Retrieve profile information about the current user.
413 request.get({ url: graphApiUrl, qs: accessToken, json: true }, function(err, response, profile) {
414 if (response.statusCode !== 200) {
415 return res.status(500).send({ message: profile.error.message });
416 }
417 if (req.header('Authorization')) {
418 User.findOne({ facebook: profile.id }, function(err, existingUser) {
419 if (existingUser) {
420 return res.status(409).send({ message: 'There is already a Facebook account that belongs to you' });
421 }
422 var token = req.header('Authorization').split(' ')[1];
423 var payload = jwt.decode(token, config.TOKEN_SECRET);
424 User.findById(payload.sub, function(err, user) {
425 if (!user) {
426 return res.status(400).send({ message: 'User not found' });
427 }
428 user.facebook = profile.id;
429 user.picture = user.picture || 'https://graph.facebook.com/v2.3/' + profile.id + '/picture?type=large';
430 user.displayName = user.displayName || profile.name;
431 user.save(function() {
432 var token = createJWT(user);
433 res.send({ token: token });
434 });
435 });
436 });
437 } else {
438 // Step 3. Create a new user account or return an existing one.
439 User.findOne({ facebook: profile.id }, function(err, existingUser) {
440 if (existingUser) {
441 var token = createJWT(existingUser);
442 return res.send({ token: token });
443 }
444 var user = new User();
445 user.facebook = profile.id;
446 user.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large';
447 user.displayName = profile.name;
448 user.save(function() {
449 var token = createJWT(user);
450 res.send({ token: token });
451 });
452 });
453 }
454 });
455 });
456});
457
458/*
459 |--------------------------------------------------------------------------
460 | Login with Twitter
461 |--------------------------------------------------------------------------
462 */
463app.post('/auth/twitter', function(req, res) {
464 var requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
465 var accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
466 var profileUrl = 'https://api.twitter.com/1.1/users/show.json?screen_name=';
467
468 // Part 1 of 2: Initial request from Satellizer.
469 if (!req.body.oauth_token || !req.body.oauth_verifier) {
470 var requestTokenOauth = {
471 consumer_key: config.TWITTER_KEY,
472 consumer_secret: config.TWITTER_SECRET,
473 callback: req.body.redirectUri
474 };
475
476 // Step 1. Obtain request token for the authorization popup.
477 request.post({ url: requestTokenUrl, oauth: requestTokenOauth }, function(err, response, body) {
478 var oauthToken = qs.parse(body);
479
480 // Step 2. Send OAuth token back to open the authorization screen.
481 res.send(oauthToken);
482 });
483 } else {
484 // Part 2 of 2: Second request after Authorize app is clicked.
485 var accessTokenOauth = {
486 consumer_key: config.TWITTER_KEY,
487 consumer_secret: config.TWITTER_SECRET,
488 token: req.body.oauth_token,
489 verifier: req.body.oauth_verifier
490 };
491
492 // Step 3. Exchange oauth token and oauth verifier for access token.
493 request.post({ url: accessTokenUrl, oauth: accessTokenOauth }, function(err, response, accessToken) {
494
495 accessToken = qs.parse(accessToken);
496
497 var profileOauth = {
498 consumer_key: config.TWITTER_KEY,
499 consumer_secret: config.TWITTER_SECRET,
500 oauth_token: accessToken.oauth_token
501 };
502
503 // Step 4. Retrieve profile information about the current user.
504 request.get({
505 url: profileUrl + accessToken.screen_name,
506 oauth: profileOauth,
507 json: true
508 }, function(err, response, profile) {
509
510 // Step 5a. Link user accounts.
511 if (req.header('Authorization')) {
512 User.findOne({ twitter: profile.id }, function(err, existingUser) {
513 if (existingUser) {
514 return res.status(409).send({ message: 'There is already a Twitter account that belongs to you' });
515 }
516
517 var token = req.header('Authorization').split(' ')[1];
518 var payload = jwt.decode(token, config.TOKEN_SECRET);
519
520 User.findById(payload.sub, function(err, user) {
521 if (!user) {
522 return res.status(400).send({ message: 'User not found' });
523 }
524
525 user.twitter = profile.id;
526 user.displayName = user.displayName || profile.name;
527 user.picture = user.picture || profile.profile_image_url.replace('_normal', '');
528 user.save(function(err) {
529 res.send({ token: createJWT(user) });
530 });
531 });
532 });
533 } else {
534 // Step 5b. Create a new user account or return an existing one.
535 User.findOne({ twitter: profile.id }, function(err, existingUser) {
536 if (existingUser) {
537 return res.send({ token: createJWT(existingUser) });
538 }
539
540 var user = new User();
541 user.twitter = profile.id;
542 user.displayName = profile.name;
543 user.picture = profile.profile_image_url.replace('_normal', '');
544 user.save(function() {
545 res.send({ token: createJWT(user) });
546 });
547 });
548 }
549 });
550 });
551 }
552});
553
554/*
555 |--------------------------------------------------------------------------
556 | Unlink Provider
557 |--------------------------------------------------------------------------
558 */
559app.post('/auth/unlink', ensureAuthenticated, function(req, res) {
560 var provider = req.body.provider;
561 var providers = ['facebook', 'google', 'twitter'];
562
563 if (providers.indexOf(provider) === -1) {
564 return res.status(400).send({ message: 'Unknown OAuth Provider' });
565 }
566
567 User.findById(req.user, function(err, user) {
568 if (!user) {
569 return res.status(400).send({ message: 'User Not Found' });
570 }
571 user[provider] = undefined;
572 user.save(function() {
573 res.status(200).end();
574 });
575 });
576});
577
578/*
579 |--------------------------------------------------------------------------
580 | Start the Server
581 |--------------------------------------------------------------------------
582 */
583app.listen(app.get('port'), function() {
584 console.log('Express server listening on port ' + app.get('port'));
585});