diff --git a/__tests__/gitlab.unit.test.js b/__tests__/gitlab.unit.test.js index af8cf6de1c3eecdd199a10a1268e4c1cf56e50a7..057f020d31d6acb893da43f021e16f4833125005 100644 --- a/__tests__/gitlab.unit.test.js +++ b/__tests__/gitlab.unit.test.js @@ -1,4 +1,4 @@ -const gitlab = require('../routes/gitlab') +const gitlab = require('../functions/gitlab') //const axios = require('axios') //jest.mock('axios') diff --git a/__tests__/method.unit.test.js b/__tests__/method.unit.test.js index 8dde44c8b285a127ac8fc8d5709db76982c98c4c..1673830dbb0fdeeceaf33a9769c76db0bdbc6c5a 100644 --- a/__tests__/method.unit.test.js +++ b/__tests__/method.unit.test.js @@ -1,52 +1,52 @@ -const methods = require('../routes/methods') +const methods = require('../functions/methods') describe("DB methohds test", () => { - it('returns a user from DB by email', done => { - methods.getUserByEmail('litehon958@whipjoy.com', function(resp, err){ - try { - expect(resp).not.toBeNull() - expect(err).toBeNull() - done() - } catch (error) { - done(error) - } - }) - }) - - it("returns a user from DB by ID", done => { - methods.getUserById(10, function(resp, err){ - try { - expect(resp).not.toBeNull() - expect(err).toBeNull() - done() - } catch (error) { - done(error) - } - }) - }) - - it("checks user email", done => { - methods.checkUserEmail("test@email.de", function(err, resp){ - try { - expect(resp).not.toBeNull() - expect(err).toBeNull() - done() - } catch (error) { - done(error) - } - }) - }) - - it("returns a user by token", done => { - methods.checkUserEmail("1abc0qwerty", function(err, resp){ // token = any alphanumeric - try { - expect(resp).not.toBeNull() - expect(err).toBeNull() - done() - } catch (error) { - done(error) - } - }) + it("returns a user from DB by email", async() => { + const user = await methods.getUserByEmail('litehon958@whipjoy.com') + expect(user).not.toBeNull() }) + it("returns a null user", async() => { + const user = await methods.getUserByEmail('jondoe@nowhere.com') // a non-exist user + expect(user).toBeNull() + }) + + it("returns a user's email", async() => { + const email = await methods.getUserEmailById(1) + expect(email).not.toBeNull() + }) + it("returns null instead of a user's email", async() => { + const email = await methods.getUserEmailById(1005) // no user has this ID + expect(email).toBeNull() + }) + + it("returns null from DB by token", async() => { + const user = await methods.getUserByToken('12345678') // unvalid token + expect(user).toBeNull() // for valid token = expect(user).not.toBeNull() + }) + + it("returns a user's verification token, if any", async() => { + const token = await methods.getVerificationTokenByUserId(1) + expect(token).toBeNull() + }) + + it("returns a user's ID, if any", async() => { + const token = await methods.getUserIdByVerificationToken('12345678') // unvalid token + expect(token).toBeNull() // for valid token = expect(user).not.toBeNull() + }) + + it("returns a user's GitLab_ID, if any", async() => { + const id = await methods.getGitlabId(1) + expect(id).not.toBeNull() + }) + + it("checks user email", async() => { + const user = await methods.checkUserEmail('litehon958@whipjoy.com') + expect(user).not.toBeNull() + }) + it("checks user email and return null", async() => { + const user = await methods.checkUserEmail('jondoe@nowhere.com') // a non-exist user + expect(user).toBeNull() + }) + }) diff --git a/functions/methods.js b/functions/methods.js index 722ca56be9fd1978ef25a0f74f004436f3b2b1d6..0037a7e143bab55cee0d9d48b71263818af86b5a 100644 --- a/functions/methods.js +++ b/functions/methods.js @@ -68,49 +68,51 @@ var methods = { getUserByEmail: async function(email) { try { let rows = await dbconn.user.promise().query('SELECT id, verificationStatus, salutation, title, firstname, lastname, industry, organisation, speciality, m4lab_idp FROM user WHERE email = "' +email+'"') - return rows[0][0] + if (rows[0][0]) { + return rows[0][0] + } + else { return null } } catch (err) { console.error(err) - return err } + return null }, - getUserById: function(userId, callback) { - dbconn_OBSOLETE.user.query('SELECT verificationStatus, email, salutation, title, firstname, lastname, industry, organisation, speciality FROM user WHERE id = ' +userId, function (err, rows, fields) { - let user - if (err) { throw err } - else { - if ( rows.length > 0) { - user = rows[0]; - } + getUserEmailById: async function(userId) { + try { + let rows = await dbconn.user.promise().query('SELECT email FROM user WHERE id = ' +userId) + if (rows[0][0]) { + return rows[0][0].email } - callback(user, err); - }); + else { return null } + } catch (err) { + console.error(err) + } + return null }, - checkUserEmail: function(email, callback) { - let user - dbconn_OBSOLETE.user.query('SELECT id, email FROM user WHERE email = "' +email+'"', function (err, rows) { - if (err) { throw err } - else { - if ( rows.length > 0) { - user = rows[0]; - } + checkUserEmail: async function(email) { + try { + let rows = await dbconn.user.promise().query('SELECT id, email FROM user WHERE email = "' +email+'"') + if (rows[0][0]) { + return rows[0][0] } - callback(err, user) - }); + else { return null } + } catch (err) { + console.error(err) + } + return null }, - getUserByToken: function(token, callback) { - let user - dbconn_OBSOLETE.user.query('SELECT t1.user_id, t2.email FROM userdb.credential AS t1 INNER JOIN userdb.user AS t2 ON t1.user_id = t2.id AND t1.resetPasswordToken = "' - +token+'" and resetPasswordExpires > '+Date.now(), function (err, rows, fields) { - if (err) { throw err } - else { - if ( rows.length > 0) { - user = rows[0] - } - } - callback(err, user) + getUserByToken: async function(token) { + try { + let rows = await dbconn.user.promise().query('SELECT t1.user_id, t2.email FROM userdb.credential AS t1 INNER JOIN userdb.user AS t2 ON t1.user_id = t2.id AND t1.resetPasswordToken = "' + +token+'" and resetPasswordExpires > '+Date.now()) + if (rows[0][0]) { + return rows[0][0] } - ) + else { return null } + } catch (err) { + console.error(err) + } + return null }, updateUserById: function(userData, callback) { dbconn_OBSOLETE.user.query('UPDATE user SET ? WHERE id = ' +userData.id, userData, function (err, rows, fields) { @@ -124,7 +126,7 @@ var methods = { callback(err) }) }, - getUserIdByEmail: function(email, callback) { + getUserIdByEmail_OBSOLETE: function(email, callback) { let userId dbconn_OBSOLETE.user.query('SELECT id FROM user WHERE email = "' +email+'"', function (err, rows, fields) { if (err) { @@ -138,7 +140,7 @@ var methods = { callback(userId, err) }); }, - getUserProjectRole: function(userId, callback) { + getUserProjectRole_OBSOLETE: function(userId, callback) { dbconn_OBSOLETE.user.query('SELECT project_id, role_id FROM user_project_role WHERE user_id = "' +userId+'"', function (err, rows, fields) { if (err) throw err callback(rows, err) @@ -150,31 +152,31 @@ var methods = { callback(err) }) }, - getVerificationTokenByUserId: function(userId, callback) { - let token - dbconn_OBSOLETE.user.query('SELECT token FROM verification WHERE user_id = "' +userId+'"', function (err, rows, fields) { - if (err) { - throw err - } - else { - if (rows.length > 0) { - token = rows[0].token - } + getVerificationTokenByUserId: async function(userId) { + try { + let rows = await dbconn.user.promise().query('SELECT token FROM verification WHERE user_id = "' +userId+'"') + if (rows[0][0]) { + return rows[0][0].token } - callback(token, err) - }) + else { return null } + } catch (err) { + console.error(err) + } + return null }, - getUserIdByVerificationToken: function(token, callback) { - let userId - dbconn_OBSOLETE.user.query('SELECT user_id FROM verification WHERE token = "' +token+'"', function (err, rows, fields) { - if (err) { - throw err + getUserIdByVerificationToken: async function(token) { + try { + let rows = await dbconn.user.promise().query('SELECT user_id FROM verification WHERE token = "' +token+'"') + if (rows[0][0]) { + return rows[0][0].user_id } - else if(rows[0]) { - userId = rows[0].user_id + else { + return null } - callback(userId, err) - }) + } catch (err) { + console.error(err) + } + return null }, verifyUserAccount: function(userData, callback) { dbconn_OBSOLETE.user.beginTransaction(function(err) { // START TRANSACTION diff --git a/routes/account.js b/routes/account.js index eb99e1fae75d320baf71d319b1e7fb9c69aa7c52..0f3b2fc7fb77929caa72ef75797173fcecfa3a4d 100644 --- a/routes/account.js +++ b/routes/account.js @@ -89,16 +89,20 @@ module.exports = function (app, config, passport, lang) { async function getLoggedInUserData(email) { let user = await methods.getUserByEmail(email) - let loggedInUser = new portalUser( - user.id, email, user.salutation, user.title, user.firstname, user.lastname, user.industry, user.organisation, user.speciality, user.m4lab_idp, null, user.verificationStatus - ) - - let userGitlabId = await methods.getGitlabId(loggedInUser.id) - if (userGitlabId) { - loggedInUser.setGitlabUserId(userGitlabId) + if (!user) { + console.log('no user found') + return null + } else { + let loggedInUser = new portalUser( + user.id, email, user.salutation, user.title, user.firstname, user.lastname, user.industry, user.organisation, user.speciality, user.m4lab_idp, null, user.verificationStatus + ) + + let userGitlabId = await methods.getGitlabId(loggedInUser.id) + if (userGitlabId) { + loggedInUser.setGitlabUserId(userGitlabId) + } + return loggedInUser } - - return loggedInUser } app.get('/', async function (req, res) { @@ -330,59 +334,39 @@ module.exports = function (app, config, passport, lang) { } }); - app.get("/resendVerificationEmail", function(req, res){ - if (req.isAuthenticated()) { - var emailAddress = req.user.email - - methods.getUserIdByEmail(req.user.email, function(userId, err) { - if (!err) { - // get token - methods.getVerificationTokenByUserId(userId, function(token, err){ - if (!err) { - if (token) { - // send email - var emailSubject = "Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto" - var emailContent = '<div>Lieber Nutzer,<br/><br/>' + - '<p>vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart. <br/>' + - 'Um Ihre Anmeldung zu bestätigen, klicken Sie bitte diesen Link: ' + config.app.host + '/verifyAccount?token=' + token + - '<br/><br/>' + - 'Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.</p><br/>' + constants.mailSignature + - '</div>'; - mailer.options.to = emailAddress; - mailer.options.subject = emailSubject; - mailer.options.html = emailContent; - mailer.transport.sendMail(mailer.options, function(err) { - if (err) { - console.log('cannot send email') - throw err - } - }) - res.send(true) - } - else { - res.send(false) - } - } - else { - console.log(err) + app.get('/resendVerificationEmail', async function(req, res){ + if (!req.isAuthenticated) { + res.redirect('/login') + } else { + let loggedInUser = await getLoggedInUserData(req.user.email) + if (!loggedInUser) { + res.redirect('/login') + } else { + let token = await methods.getVerificationTokenByUserId(loggedInUser.id) + if (!token) { + res.send(false) + } else { + // send email + var emailSubject = "Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto" + var emailContent = '<div>Lieber Nutzer,<br/><br/>' + + '<p>vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart. <br/>' + + 'Um Ihre Anmeldung zu bestätigen, klicken Sie bitte diesen Link: ' + config.app.host + '/verifyAccount?token=' + token + + '<br/><br/>' + + 'Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.</p><br/>' + constants.mailSignature + + '</div>'; + mailer.options.to = loggedInUser.email; + mailer.options.subject = emailSubject; + mailer.options.html = emailContent; + mailer.transport.sendMail(mailer.options, function(err) { + if (err) { + console.log('cannot send email') + throw err } }) - } - }) - } - }) - - app.get('/email/:email', function(req, res) { - methods.checkUserEmail(req.params.email, function(err, user){ - if (!err) { - if (user) { - res.send(false) - } - else { res.send(true) - } + } } - }) + } }) // ============= NEW GITLAB PAGES =========================== diff --git a/routes/public.js b/routes/public.js index 19ce7da250b99b0602a6d45123cc8c544a2648e8..00a243b84d2cb6f50ac4f7f53064e41427bdd95a 100644 --- a/routes/public.js +++ b/routes/public.js @@ -98,56 +98,55 @@ module.exports = function (app, config, lang) { // =================== USERS VERIFICATION ========================= - app.get("/verifyAccount", function(req, res){ - methods.getUserIdByVerificationToken(req.query.token, function(userId, err){ - if (userId) { - let userData = { - id: userId, - verificationStatus: 1 - } - methods.verifyUserAccount(userData, function(err){ - if (err) { - console.log("Error: "+err) + app.get("/verifyAccount", async function(req, res){ + let userId = await methods.getUserIdByVerificationToken(req.query.token) + if (!userId) { + // no user found + res.render(lang+'/account/verification', { + status: null + }) + } else { + // a user found, verify the account + let userData = { + id: userId, + verificationStatus: 1 + } + methods.verifyUserAccount(userData, async function(err){ + if (err) { + console.log("Error: "+err) + res.render(lang+'/account/verification', { + status: false + }); + } else { + // send welcome email after successful account verification + let userEmail = await methods.getUserEmailById(userId) + if (!userEmail) { res.render(lang+'/account/verification', { status: false - }); - } - else { - // send welcome email after successful account verification - methods.getUserById(userId, function(data, err){ - if (err) { - console.log("Error: "+err) - } - else { - // send email - var emailSubject = "Herzlich willkommen" - var emailContent = '<div>Lieber Nutzer,<br/><br/>' + - '<p>herzlich willkommen beim Transferportal der HFT Stuttgart!<br/>' + - 'Sie können nun alle Dienste des Portals nutzen.<p/><br/>' + constants.mailSignature; - mailer.options.to = data.email; - mailer.options.subject = emailSubject; - mailer.options.html = emailContent; - mailer.transport.sendMail(mailer.options, function(err) { - if (err) { - console.log('cannot send email') - throw err - } - }) - } }) - - res.render(lang+'/account/verification', { - status: true - }); + } else { + // send email + var emailSubject = "Herzlich willkommen" + var emailContent = '<div>Lieber Nutzer,<br/><br/>' + + '<p>herzlich willkommen beim Transferportal der HFT Stuttgart!<br/>' + + 'Sie können nun alle Dienste des Portals nutzen.<p/><br/>' + constants.mailSignature; + mailer.options.to = userEmail + mailer.options.subject = emailSubject + mailer.options.html = emailContent + mailer.transport.sendMail(mailer.options, function(err) { + if (err) { + console.log('cannot send email') + throw err + } + }) + + res.render(lang+'/account/verification', { + status: true + }) } - }) - } - else { - res.render(lang+'/account/verification', { - status: null - }); - } - }) + } + }) + } }) // ==================== FORGOT PASSWORD =========================== @@ -157,7 +156,7 @@ module.exports = function (app, config, lang) { user: req.user }) }) - app.post('/forgotPwd', function(req, res, next) { + app.post('/forgotPwd', function(req, res) { let emailAddress = req.body.inputEmail async.waterfall([ function(done) { @@ -166,36 +165,34 @@ module.exports = function (app, config, lang) { done(err, token) }) }, - function(token, done) { - methods.checkUserEmail(emailAddress, function(err, user){ - if (user) { - var emailSubject = "Ihre Passwort-Anfrage an das Transferportal der HFT Stuttgart"; - var emailContent = '<div>Lieber Nutzer,<br/><br/>' + - '<p>wir haben Ihre Anfrage zur Erneuerung Ihres Passwortes erhalten. Falls Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese E-Mail.<br/><br/>' + - 'Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: '+config.app.host+'/reset/' + token + '<br/>' + - 'Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.<br/></p>' + constants.mailSignature + '</div>' + async function(token) { + let user = await methods.checkUserEmail(emailAddress) + if (!user) { + console.log('no user found') + } else { + var emailSubject = "Ihre Passwort-Anfrage an das Transferportal der HFT Stuttgart"; + var emailContent = '<div>Lieber Nutzer,<br/><br/>' + + '<p>wir haben Ihre Anfrage zur Erneuerung Ihres Passwortes erhalten. Falls Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese E-Mail.<br/><br/>' + + 'Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: '+config.app.host+'/reset/' + token + '<br/>' + + 'Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.<br/></p>' + constants.mailSignature + '</div>' - var credentialData = { - user_id: user.id, - resetPasswordToken: token, - resetPasswordExpires: Date.now() + 3600000 // 1 hour - } - methods.updateCredential(credentialData, function(err) { - done(err, token, user); - }) - - // send email - mailer.options.to = emailAddress - mailer.options.subject = emailSubject - mailer.options.html = emailContent - mailer.transport.sendMail(mailer.options, function(err) { - done(err, 'done') - }); - } - else { - done(err, 'no user found') + var credentialData = { + user_id: user.id, + resetPasswordToken: token, + resetPasswordExpires: Date.now() + 3600000 // 1 hour } - }); + methods.updateCredential(credentialData, function(err) { + if (err) { console.error(err) } + }) + + // send email + mailer.options.to = emailAddress + mailer.options.subject = emailSubject + mailer.options.html = emailContent + mailer.transport.sendMail(mailer.options, function(err) { + if (err) { console.error(err) } + }) + } } ], function(err) { if (err) { @@ -205,60 +202,57 @@ module.exports = function (app, config, lang) { res.flash('success', 'Wenn Ihre E-Mail-Adresse registriert ist, wurde eine E-Mail mit dem weiteren Vorgehen an ' + emailAddress + ' versendet.') } res.redirect('/account/forgotPwd') - }); + }) }) // reset - app.get('/reset/:token', function(req, res) { - methods.getUserByToken(req.params.token, function(err, user){ - if (!user) { - res.flash('error', 'Der Schlüssel zum zurücksetzen des Passworts ist ungültig oder abgelaufen.') - res.redirect('/account/forgotPwd') - } else { - res.render(lang+'/account/reset') - } - }) + app.get('/reset/:token', async function(req, res) { + let user = await methods.getUserByToken(req.params.token) + if (!user) { + res.flash('error', 'Der Schlüssel zum zurücksetzen des Passworts ist ungültig oder abgelaufen.') + res.redirect('/account/forgotPwd') + } else { + res.render(lang+'/account/reset') + } }) - app.post('/reset/:token', function(req, res) { + app.post('/reset/:token', async function(req, res) { var newPwd = req.body.inputNewPwd - methods.getUserByToken(req.params.token, function(err, user){ - if (user) { - // encrypt password - bcrypt.genSalt(saltRounds, function(err, salt) { - bcrypt.hash(newPwd, salt, function(err, hash) { - var credentialData = { - password: hash, - user_id: user.user_id + + let user = await methods.getUserByToken(req.params.token) + if (!user) { + res.flash('error', "User not found.") + res.redirect('/login') + } else { + // encrypt password + bcrypt.genSalt(saltRounds, function(err, salt) { + bcrypt.hash(newPwd, salt, function(err, hash) { + var credentialData = { + password: hash, + user_id: user.user_id + } + // update password + methods.updateCredential(credentialData, function(err){ + if (err) { + res.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.") + throw err + } else { + res.flash('success', "Passwort aktualisiert!") + + // send notifiaction email + mailer.options.to = user.email + mailer.options.subject = constants.updatePasswordMailSubject + mailer.options.html = constants.updatePasswordMailContent+'<div>'+constants.mailSignature+'</div>' + mailer.transport.sendMail(mailer.options, function(err) { + if (err) { console.log(err) } + }) + + res.redirect('/login') } - // update password - methods.updateCredential(credentialData, function(err){ - if (err) { - res.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.") - throw err - } - else { - res.flash('success', "Passwort aktualisiert!") - // send notifiaction email - mailer.options.to = user.email - mailer.options.subject = constants.updatePasswordMailSubject - mailer.options.html = constants.updatePasswordMailContent+'<div>'+constants.mailSignature+'</div>' - mailer.transport.sendMail(mailer.options, function(err) { - if (err) { - console.log(err) - } - }); - // redirect to login page - res.redirect('/login') - } - }) - }); + }) }); - } - else { - res.flash('error', "User not found.") - res.redirect('/login') - } - }) + }); + } + }) // ======================= CONTACT FORM =========================== diff --git a/views/DE/account/home.pug b/views/DE/account/home.pug index e476d871e1acb02fc7ef20b4c53b45e6b8fc70e3..1fc325c9c961c6d445cb1714d16a46bd2827feb0 100644 --- a/views/DE/account/home.pug +++ b/views/DE/account/home.pug @@ -60,13 +60,8 @@ html(lang="de") function verify() { $(".spinner-border").show() $.get( "/resendVerificationEmail", function( data ) { - console.log(data) - if (data) { - alert( "Email sent!" ) - } - else { - alert("Please contact support-transfer@hft-stuttgart.de to verify your account.") - } + if (data) { alert( "Email sent!" ) } + else { alert("Please contact support-transfer@hft-stuttgart.de to verify your account.") } }) .fail(function() { alert( "Something went wrong. Please try again." ) // todo: to DE diff --git a/views/DE/account/verification.pug b/views/DE/account/verification.pug index 10cdea0812ca6fe472167f50d21809057929ad3c..805cceb5c959649966d9d1d23956f6ee941b36dd 100644 --- a/views/DE/account/verification.pug +++ b/views/DE/account/verification.pug @@ -22,15 +22,15 @@ html(lang="de") body div(class="container") div(class="center", align="center") - a(href="https://m4lab.hft-stuttgart.de") + a(href="https://transfer.hft-stuttgart.de") img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192") br br if status == true - p(class="h5") Ihr Benutzerkonto wurde bestätigt. Bitte <a href="https://m4lab.hft-stuttgart.de/account/">melden Sie sich an</a>. + p(class="h5") Ihr Benutzerkonto wurde bestätigt. Bitte <a href="https://transfer.hft-stuttgart.de/account/">melden Sie sich an</a>. else if status == false p(class="h5") Ihr Benutzerkonto konnte nicht bestätigt werden, bitte versuchen Sie es erneut. else - p(class="h5") Ihr Benutzerkonto wude nicht gefunden. + p(class="h5") Ihr Benutzerkonto wurde nicht gefunden. // Bootstrap script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous") \ No newline at end of file