account.ts 21.9 KB
Newer Older
Rosanny Sihombing's avatar
Rosanny Sihombing committed
1
2
3
4
5
import fs from 'fs'
import async from 'async'
import bcrypt from 'bcryptjs'
import * as passportSaml from 'passport-saml'
import dbconn from '../config/dbconn'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
6
7
import { dbController } from '../controller/dbController'
import { gitlabController } from '../controller/gitlabController'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
8
9
10
11
12
13
14
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
Rosanny Sihombing's avatar
Rosanny Sihombing committed
15
16
const saltRounds = 10
const salt = 64 // salt length
Rosanny Sihombing's avatar
Rosanny Sihombing committed
17
const logoDir = 'public/upload/'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
18
const defaultLogo: any = 'public/default/logo.png'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
19

Rosanny Sihombing's avatar
Rosanny Sihombing committed
20
export = function (app: any, config: any, passport: any, lang: string) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
21
  // =========== PASSPORT =======
Rosanny Sihombing's avatar
Rosanny Sihombing committed
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  passport.serializeUser(function (user: any, done: any) {
    done(null, user)
  })

  passport.deserializeUser(function (user: any, done: any) {
    done(null, user)
  })

  const 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
    privateKey: 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
Rosanny Sihombing's avatar
Rosanny Sihombing committed
49
  },
Rosanny Sihombing's avatar
Rosanny Sihombing committed
50
  function (profile: any, done: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
51
52
53
54
55
56
    return done(null, {
      id: profile.nameID,
      idFormat: profile.nameIDFormat,
      email: profile.email,
      firstName: profile.givenName,
      lastName: profile.sn
Rosanny Sihombing's avatar
Rosanny Sihombing committed
57
58
59
60
    })
  })

  passport.use(samlStrategy)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
61
62
63
64
65
66
67
68

  // ============= SAML ==============
  app.post(config.passport.saml.path,
    passport.authenticate(config.passport.strategy,
      {
        failureRedirect: '/account/',
        failureFlash: true
      }),
Rosanny Sihombing's avatar
Rosanny Sihombing committed
69
70
    function (req: any, res: any) {
      res.redirect('/account/')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
71
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
72
  )
Rosanny Sihombing's avatar
Rosanny Sihombing committed
73
74
75

  // to generate Service Provider's XML metadata
  app.get('/saml/metadata',
Rosanny Sihombing's avatar
Rosanny Sihombing committed
76
77
78
79
    function (req: any, res: any) {
      res.type('application/xml')
      const spMetadata = samlStrategy.generateServiceProviderMetadata(fs.readFileSync(__dirname + '/cert/cert.pem', 'utf8'))
      res.status(200).send(spMetadata)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
80
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
81
  )
Rosanny Sihombing's avatar
Rosanny Sihombing committed
82
83
84

  // ======== APP ROUTES - ACCOUNT ====================

Rosanny Sihombing's avatar
Rosanny Sihombing committed
85
  async function getLoggedInUserData (email: string) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
86
    const user = await dbController.getUserByEmail(email)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
87
88
89
90
    if (!user) {
      console.log('no user found')
      return null
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
91
      const loggedInUser = new portalUser(
Rosanny Sihombing's avatar
Rosanny Sihombing committed
92
93
        user.id, email, user.salutation, user.title, user.firstname, user.lastname, user.industry, user.organisation, user.speciality, user.m4lab_idp, user.verificationStatus
      )
Rosanny Sihombing's avatar
Rosanny Sihombing committed
94

Rosanny Sihombing's avatar
Rosanny Sihombing committed
95
      const userGitlabId = await dbController.getGitlabId(loggedInUser.id)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
96
97
98
99
100
101
102
      if (userGitlabId) {
        loggedInUser.setGitlabUserId(userGitlabId)
      }
      return loggedInUser
    }
  }

Rosanny Sihombing's avatar
Rosanny Sihombing committed
103
104
  app.get('/', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
105
106
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
107
108
109
110
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) {
        console.error('user data is not found')
        res.status(500).render(lang + '/500', { error: 'Your data is not found. Please try again.' })
111
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
112
        res.render(lang + '/account/home', {
113
          user: loggedInUser
Rosanny Sihombing's avatar
Rosanny Sihombing committed
114
        })
115
      }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
116
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
117
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
118
119
120
121
122
123
124
125

  app.get('/login',
    passport.authenticate(config.passport.strategy, {
      successRedirect: '/',
      failureRedirect: '/login'
    })
  )

Rosanny Sihombing's avatar
Rosanny Sihombing committed
126
  app.get('/logout', function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
127
    if (req.user == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
128
      return res.redirect('/')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
129
130
    }

Rosanny Sihombing's avatar
Rosanny Sihombing committed
131
132
133
134
    req.user.nameID = req.user.id
    req.user.nameIDFormat = req.user.idFormat
    return samlStrategy.logout(req, function (err: any, uri: any) {
      req.logout()
Rosanny Sihombing's avatar
Rosanny Sihombing committed
135

Rosanny Sihombing's avatar
Rosanny Sihombing committed
136
137
138
139
      if (req.session) {
        req.session.destroy((err: any) => {
          if (err) {
            return console.log(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
140
          }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
141
        })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
142
143
      }

Rosanny Sihombing's avatar
Rosanny Sihombing committed
144
145
146
      return res.redirect(uri)
    })
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
147

Rosanny Sihombing's avatar
Rosanny Sihombing committed
148
149
  app.get('/profile', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
150
151
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
152
153
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) { // null user
Rosanny Sihombing's avatar
Rosanny Sihombing committed
154
155
        res.redirect('/account/')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
156
        if (loggedInUser.getVerificationStatus() !== 1) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
157
158
          res.redirect('/account/')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
159
          res.render(lang + '/account/profile', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
160
161
162
163
164
165
166
            user: loggedInUser
          })
        }
      }
    }
  })

Rosanny Sihombing's avatar
Rosanny Sihombing committed
167
168
  app.get('/services', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
169
170
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
171
172
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) { // null user
Rosanny Sihombing's avatar
Rosanny Sihombing committed
173
174
        res.redirect('/account/')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
175
        if (loggedInUser.getVerificationStatus() !== 1) { // unverified users
Rosanny Sihombing's avatar
Rosanny Sihombing committed
176
177
          res.redirect('/account/')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
178
179
180
181
          const gitlabReposArr = []
          const gitlabPagesArr = []

          if (loggedInUser.getGitlabUserId()) { // for users who have activated their gitlab account
Rosanny Sihombing's avatar
Rosanny Sihombing committed
182
            const userProjects = await gitlabController.getUserProjects(loggedInUser.getGitlabUserId()!)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
183
            if (!userProjects) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
184
185
              console.error('something went wrong')
              res.status(500).render(lang + '/500', { error: 'something went wrong' })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
186
            }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
187
188

            let project: any
Rosanny Sihombing's avatar
Rosanny Sihombing committed
189
190
            for (project in userProjects) {
              if (userProjects[project].tag_list.includes('website')) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
191
                const page = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
192
193
                  projectInformation: new projectInformation(loggedInUser.getGitlabUserId()!, userProjects[project].name, userProjects[project].description,
                    userProjects[project].id, userProjects[project].avatar_url, userProjects[project].path_with_namespace),
Rosanny Sihombing's avatar
Rosanny Sihombing committed
194
                  pipelineStatus: await gitlabController.getProjectPipelineLatestStatus(userProjects[project].id)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
195
196
197
                }
                gitlabPagesArr.push(page)
              } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
198
                const repo = new projectRepo(loggedInUser.getGitlabUserId()!, userProjects[project].name, userProjects[project].description,
Rosanny Sihombing's avatar
Rosanny Sihombing committed
199
200
201
202
                  userProjects[project].id, userProjects[project].avatar_url, userProjects[project].path_with_namespace)
                gitlabReposArr.push(repo)
              }
            }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
203
204

            res.render(lang + '/account/services', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
205
206
207
208
209
              user: loggedInUser,
              gitlabRepos: gitlabReposArr,
              gitlabPages: gitlabPagesArr
            })
          } else { // for users who have not activated their gitlab account yet
Rosanny Sihombing's avatar
Rosanny Sihombing committed
210
            const gitlabUser = await gitlabController.getUserByEmail(loggedInUser.getEmail())
Rosanny Sihombing's avatar
Rosanny Sihombing committed
211
            if (!gitlabUser) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
212
              res.render(lang + '/account/services', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
213
214
215
216
217
                user: loggedInUser,
                gitlabRepos: null,
                gitlabPages: null
              })
            } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
218
              const gitlabActivationData = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
219
                user_id: loggedInUser.getId(),
Rosanny Sihombing's avatar
Rosanny Sihombing committed
220
221
                gitlab_userId: gitlabUser.id
              }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
222

Rosanny Sihombing's avatar
Rosanny Sihombing committed
223
              dbController.addGitlabUser(gitlabActivationData, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
224
225
                if (err) {
                  res.status(500).render(lang + '/500', { error: err })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
226
227
228
229
230
231
232
233
234
235
236
                } else {
                  res.redirect('/account/services')
                }
              })
            }
          }
        }
      }
    }
  })

Rosanny Sihombing's avatar
Rosanny Sihombing committed
237
238
  app.get('/security', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
239
240
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
241
242
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) { // null user
Rosanny Sihombing's avatar
Rosanny Sihombing committed
243
244
        res.redirect('/account/')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
245
        if (loggedInUser.getVerificationStatus() === 1 && loggedInUser.getIdpStatus() === 1) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
246
          res.render(lang + '/account/security', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
247
248
249
250
251
252
253
254
255
            user: loggedInUser
          })
        } else {
          res.redirect('/account/')
        }
      }
    }
  })

Rosanny Sihombing's avatar
Rosanny Sihombing committed
256
257
  app.post('/updateProfile', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
258
259
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
260
261
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) { // null user
Rosanny Sihombing's avatar
Rosanny Sihombing committed
262
263
        res.redirect('/account/')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
264
        const userData = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
265
266
267
268
269
270
271
          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,
Rosanny Sihombing's avatar
Rosanny Sihombing committed
272
          speciality: req.body.inputSpeciality
Rosanny Sihombing's avatar
Rosanny Sihombing committed
273
        }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
274
        const result = await dbController.updateUserById(loggedInUser.getId(), userData)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
275
        if (!result) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
276
          res.flash('error', 'Failed')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
277
278
279
280
281
282
283
284
        } 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')
      }
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
285
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
286

Rosanny Sihombing's avatar
Rosanny Sihombing committed
287
288
  app.post('/changePwd', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
289
290
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
291
      const loggedInUser = await getLoggedInUserData(req.user.email)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
292

Rosanny Sihombing's avatar
Rosanny Sihombing committed
293
      if (loggedInUser == null) { // null user
Rosanny Sihombing's avatar
Rosanny Sihombing committed
294
295
        res.redirect('/account/')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
296
297
298
        const currPwd = req.body.inputCurrPwd
        const newPwd = req.body.inputNewPwd
        const retypePwd = req.body.inputConfirm
Rosanny Sihombing's avatar
Rosanny Sihombing committed
299

Rosanny Sihombing's avatar
Rosanny Sihombing committed
300
        dbconn.user.query('SELECT password FROM credential WHERE user_id=' + loggedInUser.getId(), function (err: any, rows: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
301
302
          if (err) {
            console.error(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
303
            res.status(500).render(lang + '/500', { error: err })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
304
          }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
305
          const userPwd = rows[0].password
Rosanny Sihombing's avatar
Rosanny Sihombing committed
306
307

          // check if the password is correct
Rosanny Sihombing's avatar
Rosanny Sihombing committed
308
          bcrypt.compare(currPwd, userPwd, function (err, isMatch) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
309
310
            if (err) {
              console.error(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
311
              res.status(500).render(lang + '/500', { error: err })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
312
            } else if (!isMatch) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
313
              res.flash('error', 'Das Passwort ist leider falsch. Bitte überprüfen Sie Ihre Eingabe.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
314
315
              res.redirect('/account/security')
            } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
316
              if (newPwd != retypePwd) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
317
318
319
320
                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
Rosanny Sihombing's avatar
Rosanny Sihombing committed
321
322
323
                bcrypt.genSalt(saltRounds, function (err, salt) {
                  bcrypt.hash(newPwd, salt, async function (err, hash) {
                    const credentialData = {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
324
                      password: hash,
Rosanny Sihombing's avatar
Rosanny Sihombing committed
325
                      user_id: loggedInUser.getId()
Rosanny Sihombing's avatar
Rosanny Sihombing committed
326
                    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
327

Rosanny Sihombing's avatar
Rosanny Sihombing committed
328
                    const result = await dbController.updateCredential(credentialData)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
329
330
                    if (!result) {
                      console.log('Failed to reset password')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
331
                      res.flash('error', 'Datenbankfehler: Passwort kann nicht geändert werden.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
332
                    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
333
                      res.flash('success', 'Passwort aktualisiert!')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
334
                      // send notifiaction email
Rosanny Sihombing's avatar
Rosanny Sihombing committed
335
                      mailer.options.to = loggedInUser.getEmail()
Rosanny Sihombing's avatar
Rosanny Sihombing committed
336
                      mailer.options.subject = constants.updatePasswordMailSubject
Rosanny Sihombing's avatar
Rosanny Sihombing committed
337
338
                      mailer.options.html = constants.updatePasswordMailContent + '<div>' + constants.mailSignature + '</div>'
                      mailer.transporter.sendMail(mailer.options, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
339
340
341
342
                        if (err) { console.log(err) }
                      })
                    }
                    res.redirect('/account/security')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
343
344
                  })
                })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
345
346
347
348
349
350
              }
            }
          })
        })
      }
    }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
351
352
353
  })

  app.get('/resendVerificationEmail', async function (req: any, res: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
354
355
356
    if (!req.isAuthenticated) {
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
357
358
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
359
360
        res.redirect('/login')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
361
        const token = await dbController.getVerificationTokenByUserId(loggedInUser.id)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
362
363
364
365
        if (!token) {
          res.send(false)
        } else {
          // send email
Rosanny Sihombing's avatar
Rosanny Sihombing committed
366
367
          const emailSubject = 'Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto'
          const emailContent = '<div>Lieber Nutzer,<br/><br/>' +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
368
369
370
371
            '<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 +
Rosanny Sihombing's avatar
Rosanny Sihombing committed
372
373
374
375
376
            '</div>'
          mailer.options.to = loggedInUser.email
          mailer.options.subject = emailSubject
          mailer.options.html = emailContent
          mailer.transport.sendMail(mailer.options, function (err: any) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
377
378
379
380
381
382
383
384
385
386
387
388
            if (err) {
              console.log('cannot send email')
              throw err
            }
          })
          res.send(true)
        }
      }
    }
  })

  // ============= NEW GITLAB PAGES ===========================
Rosanny Sihombing's avatar
Rosanny Sihombing committed
389
390
391

  app.get('/newInformation', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
392
393
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
394
395
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
396
397
        res.redirect('/login')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
398
        const gitlabUser = await gitlabController.getUserByEmail(loggedInUser.getEmail())
Rosanny Sihombing's avatar
Rosanny Sihombing committed
399
400
401
        if (!gitlabUser) { // no user found
          res.redirect('/account/services')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
402
          res.render(lang + '/account/newInformation', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
403
404
405
406
407
408
409
            user: loggedInUser,
            gitlabUsername: gitlabUser.username
          })
        }
      }
    }
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
410
411
  app.post('/newInformation', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
412
413
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
414
415
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
416
417
418
419
420
421
        res.redirect('/login')
      } else {
        if (!req.body.name && !req.body.description) {
          res.flash('error', 'Bitte geben Sie die benötigten Daten ein')
          res.redirect('/account/newInformation')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
422
423
424
425
          const projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
          const projectDesc = req.body.description
          const projectTemplate = req.body.template
          const newInformation = new projectInformation(loggedInUser.getGitlabUserId()!, projectName, projectDesc)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
426
          let newLogoFile = defaultLogo
Rosanny Sihombing's avatar
Rosanny Sihombing committed
427

Rosanny Sihombing's avatar
Rosanny Sihombing committed
428
          if (req.files) { newLogoFile = req.files.logo }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
429

Rosanny Sihombing's avatar
Rosanny Sihombing committed
430
          async.waterfall([
Rosanny Sihombing's avatar
Rosanny Sihombing committed
431
            function (callback: any) { // upload logo
Rosanny Sihombing's avatar
Rosanny Sihombing committed
432
433
434
              if (!req.files) {
                callback(null, newLogoFile)
              } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
435
436
                newLogoFile.mv(logoDir + newLogoFile.name, function (err: any) {
                  newLogoFile = logoDir + newLogoFile.name
Rosanny Sihombing's avatar
Rosanny Sihombing committed
437
438
439
440
                  callback(err, newLogoFile)
                })
              }
            },
Rosanny Sihombing's avatar
Rosanny Sihombing committed
441
            async function (newLogoFile: any) { // create a new GitLab Page
Rosanny Sihombing's avatar
Rosanny Sihombing committed
442
              const newPages = await gitlabController.createNewPages(newInformation, newLogoFile, projectTemplate)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
443
              if (newPages.status) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
444
445
                if (newPages.data.message.name == 'has already been taken') {
                  res.flash('error', "Der Projektname '" + newInformation.getName() + "' ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
Rosanny Sihombing's avatar
Rosanny Sihombing committed
446
                } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
447
                  res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
448
449
450
                }
                res.redirect('/account/newInformation')
              } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
451
452
                res.flash('success', 'Ihre Webseite wurde erstellt, aber noch nicht veröffentlicht. Um Ihre Webseite endgültig zu veröffentlichen, ' +
                  'schließen Sie die Einrichtung gemäß unten stehender Anleitung ab.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
453
                res.redirect('/account/updateInformation?id=' + String(newPages.id))
Rosanny Sihombing's avatar
Rosanny Sihombing committed
454
455
456
              }
            }
          ], function (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
457
            if (err != null) console.log(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
458
459
460
            // remove logo
            if (req.files) {
              fs.unlink(newLogoFile, (err) => {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
461
                if (err != null) console.log(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
462
463
464
465
466
467
468
469
              })
            }
          })
        }
      }
    }
  })

Rosanny Sihombing's avatar
Rosanny Sihombing committed
470
471
  app.get('/updateInformation', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
472
473
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
474
      const loggedInUser = await getLoggedInUserData(req.user.email)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
475

Rosanny Sihombing's avatar
Rosanny Sihombing committed
476
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
477
478
        res.redirect('/login')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
479
        if (!req.query.id) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
480
481
          res.redirect('/account/services')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
482
          const project = await gitlabController.getProjectById(req.query.id)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
483
          if (!project) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
484
            console.log(' ========= Error or no project found')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
485
486
            res.redirect('/account/services')
          } else if (!project.owner) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
487
            console.log(' ========= Project cannot be accessed, since it does not have an owner')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
488
489
            res.redirect('/account/services')
          } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
490
            console.log(' ========= Access denied: Not your project')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
491
492
            res.redirect('/account/services')
          } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
493
            const curInformation = new projectInformation(loggedInUser.getGitlabUserId()!, project.name, project.description,
Rosanny Sihombing's avatar
Rosanny Sihombing committed
494
              req.query.id, project.avatar_url, project.path_with_namespace)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
495
496

            res.render(lang + '/account/updateInformation', {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
497
498
499
500
501
502
503
504
505
              user: loggedInUser,
              information: curInformation
            })
          }
        }
      }
    }
  })
  // update a website
Rosanny Sihombing's avatar
Rosanny Sihombing committed
506
507
  app.post('/updateInformation', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
508
509
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
510
      const loggedInUser = await getLoggedInUserData(req.user.email)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
511

Rosanny Sihombing's avatar
Rosanny Sihombing committed
512
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
513
514
515
516
517
518
        res.redirect('/login')
      } else {
        if (!req.body.name && !req.body.description) {
          res.flash('error', 'Bitte geben Sie die benötigten Daten ein')
          res.redirect('/account/updateInformation')
        } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
519
520
521
522
523
          const projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
          const projectDesc = req.body.description
          const updatedInformation = new projectInformation(loggedInUser.getGitlabUserId()!, projectName, projectDesc, req.query.id)
          let newLogoFile: any

Rosanny Sihombing's avatar
Rosanny Sihombing committed
524
          async.waterfall([
Rosanny Sihombing's avatar
Rosanny Sihombing committed
525
526
            function (callback: any) { // upload logo
              if (!req.files) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
527
528
529
                callback(null, newLogoFile)
              } else {
                newLogoFile = req.files.logo
Rosanny Sihombing's avatar
Rosanny Sihombing committed
530
531
                newLogoFile.mv(logoDir + String(newLogoFile.name), function (err: any) {
                  newLogoFile = logoDir + String(newLogoFile.name)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
532
533
534
535
                  callback(err, newLogoFile)
                })
              }
            },
Rosanny Sihombing's avatar
Rosanny Sihombing committed
536
            async function (newLogoFile: any) { // update gitlab page
Rosanny Sihombing's avatar
Rosanny Sihombing committed
537
              const updatedPages = await gitlabController.updateProject(updatedInformation, newLogoFile)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
538

Rosanny Sihombing's avatar
Rosanny Sihombing committed
539
              if (updatedPages.status) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
540
541
                if (updatedPages.data.message.name === 'has already been taken') {
                  res.flash('error', "Der Projektname '" + String(projectName) + "' ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
Rosanny Sihombing's avatar
Rosanny Sihombing committed
542
                } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
543
                  res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
544
545
546
547
                }
              } else {
                updatedInformation.setLogo(updatedPages.avatar_url)
                updatedInformation.setPath(updatedPages.path)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
548
                res.flash('success', 'Ihre Website wurde aktualisiert')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
549
550
              }

Rosanny Sihombing's avatar
Rosanny Sihombing committed
551
              res.redirect('/account/updateInformation?id=' + updatedInformation.getId())
Rosanny Sihombing's avatar
Rosanny Sihombing committed
552
553
            }
          ], function (err) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
554
555
            if (err != null) console.log(err)
            if (newLogoFile) { // remove logo
Rosanny Sihombing's avatar
Rosanny Sihombing committed
556
              fs.unlink(newLogoFile, (err) => {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
557
                if (err != null) console.log(err)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
558
559
560
561
562
563
564
565
              })
            }
          })
        }
      }
    }
  })

Rosanny Sihombing's avatar
Rosanny Sihombing committed
566
567
  app.delete('/deleteProject', async function (req: any, res: any) {
    if (!req.isAuthenticated()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
568
569
      res.redirect('/login')
    } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
570
571
      const loggedInUser = await getLoggedInUserData(req.user.email)
      if (loggedInUser == null) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
572
573
        res.redirect('/login')
      } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
574
        const projectId = req.body.id
Rosanny Sihombing's avatar
Rosanny Sihombing committed
575
576
577

        if (projectId) {
          // check if the owner is valid
Rosanny Sihombing's avatar
Rosanny Sihombing committed
578
          const project = await gitlabController.getProjectById(projectId)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
579
          if (!project) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
580
            console.log(' ========= Error or no project found')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
581
          } else if (!project.owner) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
582
            console.log(' ========= Project cannot be accessed, since it does not have an owner')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
583
          } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
584
            console.log(' ========= Access denied: Not your project')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
585
          } else {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
586
            const isDeleted = await gitlabController.deleteProjectById(projectId)
Rosanny Sihombing's avatar
Rosanny Sihombing committed
587
            if (!isDeleted) {
Rosanny Sihombing's avatar
Rosanny Sihombing committed
588
              res.flash('error', 'Project cannot be deleted. Please try again.')
Rosanny Sihombing's avatar
Rosanny Sihombing committed
589
590
591
592
593
594
595
            }
          }
        }
        res.redirect('/account/services')
      }
    }
  })
Rosanny Sihombing's avatar
Rosanny Sihombing committed
596
}