import fs from 'fs' import async from 'async' import bcrypt from 'bcryptjs' import * as passportSaml from 'passport-saml' import dbconn from '../config/dbconn' import methods from '../functions/methods' import gitlab from '../functions/gitlab' import constants from '../config/const' import mailer from '../config/mailer' import portalUser from '../classes/user' import projectInformation from '../classes/website' import projectRepo from '../classes/repo' const SamlStrategy = passportSaml.Strategy const saltRounds = 10; const salt = 64; // salt length const logoDir = 'public/upload/' const defaultLogo:any = 'public/default/logo.png' export = function (app:any, config:any, passport:any, lang:string) { // =========== PASSPORT ======= passport.serializeUser(function (user:any, done:any) { done(null, user); }); passport.deserializeUser(function (user:any, done:any) { done(null, user); }); var samlStrategy = new SamlStrategy({ // URL that goes from the Identity Provider -> Service Provider callbackUrl: config.passport.saml.path, // Base address to call logout requests logoutUrl: config.passport.saml.logoutUrl, entryPoint: config.passport.saml.entryPoint, issuer: config.passport.saml.issuer, identifierFormat: undefined, // Service Provider private key decryptionPvk: fs.readFileSync(__dirname + '/cert/key.pem', 'utf8'), // Service Provider Certificate privateCert: fs.readFileSync(__dirname + '/cert/key.pem', 'utf8'), // Identity Provider's public key cert: fs.readFileSync(__dirname + '/cert/cert_idp.pem', 'utf8'), validateInResponseTo: false, disableRequestedAuthnContext: true }, function (profile:any, done:any) { return done(null, { id: profile.nameID, idFormat: profile.nameIDFormat, email: profile.email, firstName: profile.givenName, lastName: profile.sn }); }); passport.use(samlStrategy); // ============= SAML ============== app.post(config.passport.saml.path, passport.authenticate(config.passport.strategy, { failureRedirect: '/account/', failureFlash: true }), function (req:any, res:any) { res.redirect('/account/'); } ); // to generate Service Provider's XML metadata app.get('/saml/metadata', function(req:any, res:any) { res.type('application/xml'); var spMetadata = samlStrategy.generateServiceProviderMetadata(fs.readFileSync(__dirname + '/cert/cert.pem', 'utf8')); res.status(200).send(spMetadata); } ); // ======== APP ROUTES - ACCOUNT ==================== async function getLoggedInUserData(email:string) { let user = await methods.getUserByEmail(email) 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, user.verificationStatus ) let userGitlabId = await methods.getGitlabId(loggedInUser.id) if (userGitlabId) { loggedInUser.setGitlabUserId(userGitlabId) } return loggedInUser } } app.get('/', async function (req:any, res:any) { if ( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) res.render(lang+'/account/home', { user: loggedInUser }); } }); app.get('/login', passport.authenticate(config.passport.strategy, { successRedirect: '/', failureRedirect: '/login' }) ) app.get('/logout', function (req:any, res:any) { if (req.user == null) { return res.redirect('/'); } req.user.nameID = req.user.id; req.user.nameIDFormat = req.user.idFormat; return samlStrategy.logout(req, function(err:any, uri:any) { req.logout(); if ( req.session ) { req.session.destroy((err:any) => { if(err) { return console.log(err); } }); } return res.redirect(uri); }); }); app.get('/profile', async function (req:any, res:any) { if ( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) if (!loggedInUser) { // null user res.redirect('/account/') } else { if(loggedInUser.getVerificationStatus() != 1) { res.redirect('/account/') } else { res.render(lang+'/account/profile', { user: loggedInUser }) } } } }) app.get('/services', async function(req:any, res:any){ if( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) if (!loggedInUser) { // null user res.redirect('/account/') } else { if(loggedInUser.getVerificationStatus() != 1) { // unverified users res.redirect('/account/') } else { let gitlabReposArr = [] let gitlabPagesArr = [] if(loggedInUser.getGitlabUserId()) { // for users who have activated their gitlab account let userProjects = await gitlab.getUserProjects(loggedInUser.getGitlabUserId()!) if (!userProjects) { console.error("something went wrong") res.status(500).render(lang+'/500', { error: "something went wrong" }) } let project:any for (project in userProjects) { if (userProjects[project].tag_list.includes('website')) { let page = { projectInformation: new projectInformation(loggedInUser.getGitlabUserId()!, userProjects[project].name, userProjects[project].description, userProjects[project].id, userProjects[project].avatar_url, userProjects[project].path_with_namespace), pipelineStatus: await gitlab.getProjectPipelineLatestStatus(userProjects[project].id) } gitlabPagesArr.push(page) } else { let repo = new projectRepo(loggedInUser.getGitlabUserId()!, userProjects[project].name, userProjects[project].description, userProjects[project].id, userProjects[project].avatar_url, userProjects[project].path_with_namespace) gitlabReposArr.push(repo) } } res.render(lang+'/account/services', { user: loggedInUser, gitlabRepos: gitlabReposArr, gitlabPages: gitlabPagesArr }) } else { // for users who have not activated their gitlab account yet let gitlabUser = await gitlab.getUserByEmail(loggedInUser.getEmail()) if (!gitlabUser) { res.render(lang+'/account/services', { user: loggedInUser, gitlabRepos: null, gitlabPages: null }) } else { let gitlabActivationData = { user_id: loggedInUser.getId(), gitlab_userId: gitlabUser.id} methods.addGitlabUser(gitlabActivationData, function(err:any){ if(err) { res.status(500).render(lang+'/500', { error: err }) } else { res.redirect('/account/services') } }) } } } } } }) app.get('/security', async function (req:any, res:any) { if ( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) if (!loggedInUser) { // null user res.redirect('/account/') } else { if(loggedInUser.getVerificationStatus() == 1 && loggedInUser.getIdpStatus() == 1) { res.render(lang+'/account/security', { user: loggedInUser }) } else { res.redirect('/account/') } } } }) app.post('/updateProfile', async function (req:any, res:any) { if ( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) if (!loggedInUser) { // null user res.redirect('/account/') } else { let userData = { salutation: req.body.inputSalutation, title: req.body.inputTitle, firstname: req.body.inputFirstname, lastname: req.body.inputLastname, email: req.body.inputEmail, organisation: req.body.inputOrganisation, industry: req.body.inputIndustry, speciality: req.body.inputSpeciality, } let result = await methods.updateUserById(loggedInUser.getId(), userData) if (!result) { res.flash('error', "Failed") } else { loggedInUser.updateProfile(userData.salutation, userData.title, userData.firstname, userData.lastname, userData.email, userData.organisation, userData.industry, userData.speciality) res.flash('success', 'Ihr Benutzerprofil wurde aktualisiert!') } res.redirect('/account/profile') } } }); app.post('/account/changePwd', async function (req:any, res:any) { if( !req.isAuthenticated() ) { res.redirect('/login') } else { let loggedInUser = await getLoggedInUserData(req.user.email) if (!loggedInUser) { // null user res.redirect('/account/') } else { let currPwd = req.body.inputCurrPwd let newPwd = req.body.inputNewPwd let retypePwd = req.body.inputConfirm dbconn.user.query('SELECT password FROM credential WHERE user_id='+loggedInUser.getId(), function (err, rows, fields) { if (err) { console.error(err) res.status(500).render(lang+'/500', { error: err }) } var userPwd = rows[0].password // check if the password is correct bcrypt.compare(currPwd, userPwd, function(err, isMatch) { if (err) { console.error(err) res.status(500).render(lang+'/500', { error: err }) } else if (!isMatch) { res.flash('error', "Das Passwort ist leider falsch. Bitte überprüfen Sie Ihre Eingabe.") res.redirect('/account/security') } else { if ( newPwd != retypePwd ) { res.flash('error', 'Passwörter stimmen nicht überein. Bitte stellen Sie sicher, dass Sie das Passwort beide Male genau gleich eingeben.') res.redirect('/account/security') } else { // update password bcrypt.genSalt(saltRounds, function(err, salt) { bcrypt.hash(newPwd, salt, async function(err, hash) { var credentialData = { password: hash, user_id: loggedInUser!.getId() } let result = await methods.updateCredential(credentialData) if (!result) { console.log('Failed to reset password') res.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.") } else { res.flash('success', "Passwort aktualisiert!") // send notifiaction email mailer.options.to = loggedInUser!.getEmail() mailer.options.subject = constants.updatePasswordMailSubject mailer.options.html = constants.updatePasswordMailContent+'
vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart.
' +
'Um Ihre Anmeldung zu bestätigen, klicken Sie bitte diesen Link: ' + config.app.host + '/verifyAccount?token=' + token +
'
' +
'Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.