public.ts 10.2 KB
Newer Older
Rosanny Sihombing's avatar
Rosanny Sihombing committed
1
2
import async from 'async'
import bcrypt from 'bcryptjs'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
3
import { dbController } from '../controller/dbController'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
4
5
import mailer from '../config/mailer'
import constants from '../config/const'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
6
import { publicController } from '../controller/publicController'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
7

Rosanny Sihombing's avatar
Rosanny Sihombing committed
8
9
const saltRounds: number = 10
const salt: number = 64
Rosanny Sihombing's avatar
Rosanny Sihombing committed
10

Rosanny Sihombing's avatar
Rosanny Sihombing committed
11
export = function (app: any, config: any, lang: string) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
12
  // ================== NEW USERS REGISTRATION ======================
Rosanny Sihombing's avatar
Rosanny Sihombing committed
13
  app.get('/registration', function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
14
    publicController.showRegistrationPage(res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
15
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
16
  app.post('/registration', function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
17
    // user data
Rosanny Sihombing's avatar
Rosanny Sihombing committed
18
19
    const curDate: Date = new Date()
    const userData: any = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
20
21
22
23
24
25
26
27
      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,
Rosanny Sihombing's avatar
Rosanny Sihombing committed
28
      createdDate: curDate.toISOString().slice(0, 10)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
29
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
30
31
32
33
34
35
36
37

    const userEmail: any = userData.email
    const pos: number = userEmail.indexOf('@')
    const emailLength: number = userEmail.length
    const emailDomain: any = userEmail.slice(pos, emailLength)

    if (emailDomain.toLowerCase() == '@hft-stuttgart.de') {
      res.flash('error', 'Fehlgeschlagen: HFT-Account')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
38
39
40
      res.redirect('/account/registration')
    } else {
      async.waterfall([
Rosanny Sihombing's avatar
Rosanny Sihombing committed
41
        function (done: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
42
          // generate token
Rosanny Sihombing's avatar
Rosanny Sihombing committed
43
44
45
46
          let token: string = ''
          const randomChars: string = 'abcdefghijklmnopqrstuvwxyz0123456789'
          for (let i = 0; i < 40; i++) {
            token += randomChars.charAt(Math.floor(Math.random() * randomChars.length))
Rosanny Sihombing's avatar
Rosanny Sihombing committed
47
48
          }
          // encrypt password
Rosanny Sihombing's avatar
Rosanny Sihombing committed
49
50
51
          bcrypt.genSalt(saltRounds, function (err, salt) {
            bcrypt.hash(req.body.inputPassword, salt, function (err: any, hash: any) {
              const newAccount: any = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
52
53
54
55
56
                profile: userData,
                password: hash,
                verificationToken: token
              }
              done(err, newAccount)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
57
58
            })
          })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
59
60
        },
        // save data
Rosanny Sihombing's avatar
Rosanny Sihombing committed
61
        function (newAccount: any, err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
62
          dbController.registerNewUser(newAccount, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
63
            if (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
64
65
              res.flash('error', 'Fehlgeschlagen')
            } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
66
              // send email
Rosanny Sihombing's avatar
Rosanny Sihombing committed
67
68
              const emailSubject = 'Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto'
              const emailContent = '<div>Lieber Nutzer,<br/><br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
69
                '<p>vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart. <br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
70
                'Um Ihre Anmeldung zu bestätigen, klicken Sie bitte <a href=' + String(config.app.host) + '/verifyAccount?token=' + String(newAccount.verificationToken) + '>diesen Link</a> ' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
71
                '<br/><br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
72
                'Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.</p><br/>' + String(constants.mailSignature) +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
73
74
75
76
77
                '</div>'
              mailer.options.to = req.body.inputEmail
              mailer.options.subject = emailSubject
              mailer.options.html = emailContent
              mailer.transporter.sendMail(mailer.options, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
78
                if (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
79
                  console.error('Cannot send email. [Error] ' + String(err))
Rosanny Sihombing's avatar
Rosanny Sihombing committed
80
81
82
83
                  throw err
                }
              })
              // user feedback
Rosanny Sihombing's avatar
Rosanny Sihombing committed
84
85
              res.flash('success', 'Vielen Dank für Ihre Registrierung!' + '\r\n\r\n' +
                'Wir haben Ihnen eine E-Mail an Ihre verwendete Adresse gesendet. Diese enthält einen Link zur Bestätigung Ihres Accounts.' + '\r\n' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
86
                'Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
87
88
89
            }
            res.redirect('/account/registration')
          })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
90
91
92
93
        }
      ])
    }
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
94
  // to check whether or not an account is already exist
Rosanny Sihombing's avatar
Rosanny Sihombing committed
95
  app.get('/email/:email', async function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
96
    publicController.checkUserEmail(req, res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
97
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
98
99
100

  // =================== USERS VERIFICATION =========================

Rosanny Sihombing's avatar
Rosanny Sihombing committed
101
  app.get('/verifyAccount', async function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
102
    const userId: number = await dbController.getUserIdByVerificationToken(req.query.token)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
103
104
    if (!userId) {
      // no user found
Rosanny Sihombing's avatar
Rosanny Sihombing committed
105
      res.render(lang + '/account/verification', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
106
107
108
109
        status: null
      })
    } else {
      // a user found, verify the account
Rosanny Sihombing's avatar
Rosanny Sihombing committed
110
      const userData: any = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
111
112
113
        id: userId,
        verificationStatus: 1
      }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
114
      dbController.verifyUserAccount(userData, async function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
115
        if (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
116
          console.error(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
117
          res.render(lang + '/account/verification', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
118
            status: false
Rosanny Sihombing's avatar
Rosanny Sihombing committed
119
          })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
120
121
        } else {
          // send welcome email after successful account verification
Rosanny Sihombing's avatar
Rosanny Sihombing committed
122
          const userEmail: string = await dbController.getUserEmailById(userId)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
123
          if (!userEmail) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
124
            res.render(lang + '/account/verification', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
125
126
127
128
              status: false
            })
          } else {
            // send email
Rosanny Sihombing's avatar
Rosanny Sihombing committed
129
130
            const emailSubject = 'Herzlich willkommen'
            const emailContent = '<div>Lieber Nutzer,<br/><br/>' +
131
              '<p>herzlich willkommen beim Transferportal der HFT Stuttgart!<br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
132
133
134
135
136
              '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.transporter.sendMail(mailer.options, function (err: any) {
137
              if (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
138
139
                console.log('cannot send email')
                throw err
140
141
              }
            })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
142
143

            res.render(lang + '/account/verification', {
144
145
              status: true
            })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
146
147
          }
        }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
148
      })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
149
150
151
152
153
    }
  })

  // ==================== FORGOT PASSWORD ===========================

Rosanny Sihombing's avatar
Rosanny Sihombing committed
154
  app.get('/forgotPwd', function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
155
    publicController.showForgotPwdPage(req, res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
156
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
157
158
  app.post('/forgotPwd', function (req: any, res: any) {
    const emailAddress = req.body.inputEmail
Rosanny Sihombing's avatar
Rosanny Sihombing committed
159
    async.waterfall([
Rosanny Sihombing's avatar
Rosanny Sihombing committed
160
      async function (done: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
161
        const user = await dbController.checkUserEmail(emailAddress)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
162
        if (!user) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
163
          console.log('No user found: ' + String(emailAddress))
Rosanny Sihombing's avatar
Rosanny Sihombing committed
164
165
        } else {
          // generate token
Rosanny Sihombing's avatar
Rosanny Sihombing committed
166
167
168
169
          let token: string = ''
          const randomChars: string = 'abcdefghijklmnopqrstuvwxyz0123456789'
          for (let i = 0; i < 40; i++) {
            token += randomChars.charAt(Math.floor(Math.random() * randomChars.length))
Rosanny Sihombing's avatar
Rosanny Sihombing committed
170
171
          }

Rosanny Sihombing's avatar
Rosanny Sihombing committed
172
173
          const emailSubject = 'Ihre Passwort-Anfrage an das Transferportal der HFT Stuttgart'
          const emailContent = '<div>Lieber Nutzer,<br/><br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
174
            '<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/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
175
176
            'Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: ' + String(config.app.host) + '/reset/' + String(token) + '<br/>' +
            'Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.<br/></p>' + String(constants.mailSignature) + '</div>'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
177
178

          const credentialData = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
179
180
181
182
            user_id: user.id,
            resetPasswordToken: token,
            resetPasswordExpires: Date.now() + 3600000 // 1 hour
          }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
183
          const result = await dbController.updateCredential(credentialData)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
184
185
186
187
188
189
190
          if (!result) {
            console.log('failed to update credential')
          } else {
            // send email
            mailer.options.to = emailAddress
            mailer.options.subject = emailSubject
            mailer.options.html = emailContent
Rosanny Sihombing's avatar
Rosanny Sihombing committed
191
            mailer.transporter.sendMail(mailer.options, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
192
193
194
195
196
197
              if (err) { console.error(err) }
            })
          }
        }
        done(null)
      }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
198
    ], function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
199
200
      if (err) {
        res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
201
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
202
        res.flash('success', 'Wenn Ihre E-Mail-Adresse registriert ist, wurde eine E-Mail mit dem weiteren Vorgehen an ' + String(emailAddress) + ' versendet.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
203
204
205
206
207
208
      }
      res.redirect('/account/forgotPwd')
    })
  })

  // reset
Rosanny Sihombing's avatar
Rosanny Sihombing committed
209
  app.get('/reset/:token', async function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
210
    publicController.showResetToken(req, res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
211
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
212
213
  app.post('/reset/:token', async function (req: any, res: any) {
    const newPwd = req.body.inputNewPwd
Rosanny Sihombing's avatar
Rosanny Sihombing committed
214

Rosanny Sihombing's avatar
Rosanny Sihombing committed
215
    const user = await dbController.getUserByToken(req.params.token)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    if (!user) {
      res.flash('error', 'User not found.')
      res.redirect('/login')
    } else {
      // encrypt password
      bcrypt.genSalt(saltRounds, function (err, salt) {
        bcrypt.hash(newPwd, salt, async function (err: any, hash) {
          const credentialData = {
            password: hash,
            user_id: user.user_id,
            resetPasswordToken: null,
            resetPasswordExpires: null
          }
          // update password
Rosanny Sihombing's avatar
Rosanny Sihombing committed
230
          const result = await dbController.updateCredential(credentialData)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
          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 notification email
            mailer.options.to = user.email
            mailer.options.subject = constants.updatePasswordMailSubject
            mailer.options.html = constants.updatePasswordMailContent + '<div>' + constants.mailSignature + '</div>'
            mailer.transporter.sendMail(mailer.options, function (err: any) {
              if (err) { console.log(err) }
            })
          }
          res.redirect('/login')
        })
      })
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
248
249
250
  })

  // ======================= CONTACT FORM ===========================
Rosanny Sihombing's avatar
Rosanny Sihombing committed
251
  app.get('/contact', function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
252
    publicController.showContactPage(req, res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
253
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
254
255
  app.post('/contact', function (req: any, res: any) {
    publicController.sendContactMessage(req, res)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
256
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
257
}