user.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. var async = require('async');
  2. var crypto = require('crypto');
  3. var nodemailer = require('nodemailer');
  4. var passport = require('passport');
  5. var User = require('../models/User');
  6. /**
  7. * Login required middleware
  8. */
  9. exports.ensureAuthenticated = function(req, res, next) {
  10. if (req.isAuthenticated()) {
  11. next();
  12. } else {
  13. res.redirect('/login');
  14. }
  15. };
  16. /**
  17. * GET /login
  18. */
  19. exports.loginGet = function(req, res) {
  20. if (req.user) {
  21. return res.redirect('/');
  22. }
  23. res.render('account/login', {
  24. title: 'Log in'
  25. });
  26. };
  27. /**
  28. * POST /login
  29. */
  30. exports.loginPost = function(req, res, next) {
  31. req.assert('email', 'O e-mail inserido não é válido').isEmail();
  32. req.assert('email', 'O e-mail não pode ficar em branco').notEmpty();
  33. req.assert('password', 'A senha não pode ficar em branco').notEmpty();
  34. req.sanitize('email').normalizeEmail({ remove_dots: false });
  35. var errors = req.validationErrors();
  36. if (errors) {
  37. req.flash('error', errors);
  38. return res.redirect('/login');
  39. }
  40. passport.authenticate('local', function(err, user, info) {
  41. if (!user) {
  42. req.flash('error', info);
  43. return res.redirect('/login')
  44. }
  45. req.logIn(user, function(err) {
  46. res.redirect('/');
  47. });
  48. })(req, res, next);
  49. };
  50. /**
  51. * GET /logout
  52. */
  53. exports.logout = function(req, res) {
  54. req.logout();
  55. res.redirect('/');
  56. };
  57. /**
  58. * GET /signup
  59. */
  60. exports.signupGet = function(req, res) {
  61. if (req.user) {
  62. return res.redirect('/');
  63. }
  64. res.render('account/signup', {
  65. title: 'Criar conta'
  66. });
  67. };
  68. /**
  69. * POST /signup
  70. */
  71. exports.signupPost = function(req, res, next) {
  72. req.assert('name', 'O nome não pode ficar em branco').notEmpty();
  73. req.assert('email', 'O e-mail inserido não é válido').isEmail();
  74. req.assert('email', 'O e-mail não pode ficar em branco').notEmpty();
  75. req.assert('password', 'A senha precisa ter pelo menos 4 caracteres').len(4);
  76. req.sanitize('email').normalizeEmail({ remove_dots: false });
  77. var errors = req.validationErrors();
  78. if (errors) {
  79. req.flash('error', errors);
  80. return res.redirect('/signup');
  81. }
  82. User.findOne({ email: req.body.email }, function(err, user) {
  83. if (user) {
  84. req.flash('error', { msg: 'O e-mail inserido já está associado com outra conta.' });
  85. return res.redirect('/signup');
  86. }
  87. user = new User({
  88. name: req.body.name,
  89. username: req.body.username,
  90. email: req.body.email,
  91. password: req.body.password
  92. });
  93. user.save(function(err) {
  94. req.logIn(user, function(err) {
  95. res.redirect('/');
  96. });
  97. });
  98. });
  99. };
  100. /**
  101. * GET /account
  102. */
  103. exports.accountGet = function(req, res) {
  104. res.render('account/profile', {
  105. title: 'Minha Conta'
  106. });
  107. };
  108. /**
  109. * PUT /account
  110. * Update profile information OR change password.
  111. */
  112. exports.accountPut = function(req, res, next) {
  113. if ('password' in req.body) {
  114. req.assert('password', 'A senha precisa ter pelo menos 4 caracteres.').len(4);
  115. req.assert('confirm', 'As senhas inseridas não conferem.').equals(req.body.password);
  116. } else {
  117. req.assert('email', 'Este e-mail não é válido.').isEmail();
  118. req.assert('email', 'O campo "Email" precisa ser preenchido.').notEmpty();
  119. req.sanitize('email').normalizeEmail({ remove_dots: false });
  120. }
  121. var errors = req.validationErrors();
  122. if (errors) {
  123. req.flash('error', errors);
  124. return res.redirect('/account');
  125. }
  126. User.findById(req.user.id, function(err, user) {
  127. if ('password' in req.body) {
  128. user.password = req.body.password;
  129. } else {
  130. user.email = req.body.email;
  131. user.username = req.body.username;
  132. user.name = req.body.name;
  133. user.gender = req.body.gender;
  134. user.location = req.body.location;
  135. user.website = req.body.website;
  136. }
  137. user.save(function(err) {
  138. if ('password' in req.body) {
  139. req.flash('success', { msg: 'Sua senha foi redefinida com sucesso.' });
  140. } else if (err && err.code === 11000) {
  141. req.flash('error', { msg: 'E-mail ou username inseridos já estão associados com outra conta.' });
  142. } else {
  143. req.flash('success', { msg: 'Suas informações foram alteradas com sucesso.' });
  144. }
  145. res.redirect('/account');
  146. });
  147. });
  148. };
  149. /**
  150. * DELETE /account
  151. */
  152. exports.accountDelete = function(req, res, next) {
  153. User.remove({ _id: req.user.id }, function(err) {
  154. req.logout();
  155. req.flash('info', { msg: 'Sua conta foi foi excluída com sucesso.' });
  156. res.redirect('/');
  157. });
  158. };
  159. /**
  160. * GET /unlink/:provider
  161. */
  162. exports.unlink = function(req, res, next) {
  163. User.findById(req.user.id, function(err, user) {
  164. switch (req.params.provider) {
  165. case 'facebook':
  166. user.facebook = undefined;
  167. break;
  168. case 'google':
  169. user.google = undefined;
  170. break;
  171. case 'twitter':
  172. user.twitter = undefined;
  173. break;
  174. case 'vk':
  175. user.vk = undefined;
  176. break;
  177. case 'github':
  178. user.github = undefined;
  179. break;
  180. default:
  181. req.flash('error', { msg: 'Invalid OAuth Provider' });
  182. return res.redirect('/account');
  183. }
  184. user.save(function(err) {
  185. req.flash('success', { msg: 'Your account has been unlinked.' });
  186. res.redirect('/account');
  187. });
  188. });
  189. };
  190. /**
  191. * GET /forgot
  192. */
  193. exports.forgotGet = function(req, res) {
  194. if (req.isAuthenticated()) {
  195. return res.redirect('/');
  196. }
  197. res.render('account/forgot', {
  198. title: 'Esqueci a Senha'
  199. });
  200. };
  201. /**
  202. * POST /forgot
  203. */
  204. exports.forgotPost = function(req, res, next) {
  205. req.assert('email', 'O e-mail não é válido').isEmail();
  206. req.assert('email', ' e-mail não pode ficar em branco').notEmpty();
  207. req.sanitize('email').normalizeEmail({ remove_dots: false });
  208. var errors = req.validationErrors();
  209. if (errors) {
  210. req.flash('error', errors);
  211. return res.redirect('/forgot');
  212. }
  213. async.waterfall([
  214. function(done) {
  215. crypto.randomBytes(16, function(err, buf) {
  216. var token = buf.toString('hex');
  217. done(err, token);
  218. });
  219. },
  220. function(token, done) {
  221. User.findOne({ email: req.body.email }, function(err, user) {
  222. if (!user) {
  223. req.flash('error', { msg: 'O endereço de e-mail ' + req.body.email + ' não está associado com nenhuma conta.' });
  224. return res.redirect('/forgot');
  225. }
  226. user.passwordResetToken = token;
  227. user.passwordResetExpires = Date.now() + 3600000; // expire in 1 hour
  228. user.save(function(err) {
  229. done(err, token, user);
  230. });
  231. });
  232. },
  233. function(token, user, done) {
  234. var transporter = nodemailer.createTransport({
  235. service: 'Mailgun',
  236. auth: {
  237. user: process.env.MAILGUN_USERNAME,
  238. pass: process.env.MAILGUN_PASSWORD
  239. }
  240. });
  241. var mailOptions = {
  242. to: user.email,
  243. from: 'suporte@acredito.me',
  244. subject: 'Redefinir sua senha no Acredito.me',
  245. text: 'Você está recebendo isso porque você (ou alguma outra pessoa) pediu para redefenir a senha da sua conta.\n\n' +
  246. 'Por favor, clieque no link a seguir, ou cole no seu navegador para completar esse processo:\n\n' +
  247. 'https://' + req.headers.host + '/reset/' + token + '\n\n' +
  248. 'Se você não pediu essa redefinição, por favor ignore este e-mail e a sua senha não sofrerá nenhuma alteração.\n' +
  249. 'Obrigado por salvar vidas com o acredito.me\n'
  250. };
  251. transporter.sendMail(mailOptions, function(err) {
  252. req.flash('info', { msg: 'Um e-mail foi enviado para ' + user.email + ' com mais informações.' });
  253. res.redirect('/forgot');
  254. });
  255. }
  256. ]);
  257. };
  258. /**
  259. * GET /reset
  260. */
  261. exports.resetGet = function(req, res) {
  262. if (req.isAuthenticated()) {
  263. return res.redirect('/');
  264. }
  265. User.findOne({ passwordResetToken: req.params.token })
  266. .where('passwordResetExpires').gt(Date.now())
  267. .exec(function(err, user) {
  268. if (!user) {
  269. req.flash('error', { msg: 'Password reset token is invalid or has expired.' });
  270. return res.redirect('/forgot');
  271. }
  272. res.render('account/reset', {
  273. title: 'Redefinir Senha'
  274. });
  275. });
  276. };
  277. /**
  278. * POST /reset
  279. */
  280. exports.resetPost = function(req, res, next) {
  281. req.assert('password', 'A senha precisa ter ao menos 4 caracteres').len(4);
  282. req.assert('confirm', 'A senhas não são iguais').equals(req.body.password);
  283. var errors = req.validationErrors();
  284. if (errors) {
  285. req.flash('error', errors);
  286. return res.redirect('back');
  287. }
  288. async.waterfall([
  289. function(done) {
  290. User.findOne({ passwordResetToken: req.params.token })
  291. .where('passwordResetExpires').gt(Date.now())
  292. .exec(function(err, user) {
  293. if (!user) {
  294. req.flash('error', { msg: 'Password reset token is invalid or has expired.' });
  295. return res.redirect('back');
  296. }
  297. user.password = req.body.password;
  298. user.passwordResetToken = undefined;
  299. user.passwordResetExpires = undefined;
  300. user.save(function(err) {
  301. req.logIn(user, function(err) {
  302. done(err, user);
  303. });
  304. });
  305. });
  306. },
  307. function(user, done) {
  308. var transporter = nodemailer.createTransport({
  309. service: 'Mailgun',
  310. auth: {
  311. user: process.env.MAILGUN_USERNAME,
  312. pass: process.env.MAILGUN_PASSWORD
  313. }
  314. });
  315. var mailOptions = {
  316. from: 'suporte@acredito.me',
  317. to: user.email,
  318. subject: 'Sua senha no acredito.me foi alterada',
  319. text: 'Hello,\n\n' +
  320. 'Este e-mail é uma confirmação que a senha da sua conta no acredito.me (' + user.email + ') foi alterada recentemente.\n'
  321. };
  322. transporter.sendMail(mailOptions, function(err) {
  323. req.flash('success', { msg: 'Sua senha foi alterada com sucesso.' });
  324. res.redirect('/account');
  325. });
  326. }
  327. ]);
  328. };