diff --git a/app.js b/app.js
deleted file mode 100644
index b5aac0bc6362999b0cb402096628af41d12a362c..0000000000000000000000000000000000000000
--- a/app.js
+++ /dev/null
@@ -1,82 +0,0 @@
-const express = require('express');
-const http = require('http');
-const path = require('path');
-const passport = require('passport');
-const morgan = require('morgan');
-const cookieParser = require('cookie-parser');
-const bodyParser = require('body-parser');
-const session = require('express-session');
-const errorhandler = require('errorhandler');
-const flash = require('express-flash-2');
-const fileUpload = require('express-fileupload');
-const helmet = require('helmet');
-const compression = require('compression');
-const methodOverride = require('method-override');
-
-var env = process.env.NODE_ENV || 'testing';
-const config = require('./config/config')[env];
-const lang = 'DE';
-
-var app = express();
-
-app.set('port', config.app.port);
-app.set('views', __dirname + '/views');
-app.set('view engine', 'pug');
-
-// enable files upload
-app.use(fileUpload({
-  createParentPath: true,
-  limits: { 
-    fileSize: 1000000 // 1 MB max. file size
-  }
-}));
-
-app.use(methodOverride('_method'));
-app.use(helmet());
-app.use(compression());
-app.use(morgan('combined'));
-app.use(cookieParser());
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({extended: false}));
-app.use(express.static(path.join(__dirname, 'public')));
-app.use((req, res, next) => {
-  next();
-});
-
-app.use(session(
-  {
-    resave: true,
-    saveUninitialized: true,
-    secret: config.app.sessionSecret
-  }
-));
-app.use(flash());
-app.use(passport.initialize());
-app.use(passport.session());
-
-// caching disabled for every route
-// NOTE: Works in Firefox and Opera. Does not work in Edge
-app.use(function(req, res, next) {
-  res.set('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
-  next();
-});
-
-require('./routes/account')(app, config, passport, lang);
-require('./routes/public')(app, config, lang);
-
-// Handle 404
-app.use(function (req, res) {
-  res.status(404).render(lang+'/404')
-})
-
-// Handle 500 - any server error
-app.use(function (err, req, res, next) {
-  console.error(err.stack)
-  res.status(500).render(lang+'/500', {
-    error: err
-  })
-})
-
-app.listen(app.get('port'), function () {
-  console.log('Express server listening on port ' + app.get('port'));
-});
\ No newline at end of file
diff --git a/app.ts b/app.ts
new file mode 100644
index 0000000000000000000000000000000000000000..89a8a359589fd6220aeab4f5ec4e14e0c742df46
--- /dev/null
+++ b/app.ts
@@ -0,0 +1,93 @@
+import express from 'express';
+import path from 'path';
+import passport from 'passport';
+import morgan from 'morgan';
+import cookieParser from 'cookie-parser';
+import bodyParser from 'body-parser';
+import session from 'express-session';
+import flash from 'express-flash-2';
+import fileUpload from 'express-fileupload';
+import helmet from 'helmet';
+import compression from 'compression';
+import methodOverride from 'method-override';
+import dotenv from 'dotenv'
+
+dotenv.config();
+
+var env = process.env.NODE_ENV || 'testing';
+const config = require('./config/config')[env];
+const lang = 'DE';
+
+var app = express();
+app.set('port', config.app.port);
+app.set('views', path.join( __dirname + '/views'));
+app.set('view engine', 'pug');
+
+// enable files upload
+app.use(fileUpload({
+  createParentPath: true,
+  limits: { 
+    fileSize: 1000000 // 1 MB max. file size
+  }
+}));
+app.use(methodOverride('_method'));
+app.use(
+  helmet.contentSecurityPolicy({
+    useDefaults: true,
+    directives: {
+      "font-src": ["'self'", "https://use.fontawesome.com"],
+      "img-src": ["'self'", "https://transfer.hft-stuttgart.de"],
+      "script-src": ["'self'", "https://code.jquery.com/jquery-3.3.1.min.js", "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", 
+        "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", "https://unpkg.com/bootstrap-show-password@1.2.1/dist/bootstrap-show-password.min.js"],
+      "style-src": ["'self'", "https://use.fontawesome.com/releases/v5.8.2/css/all.css"],
+      "frame-src": ["'self'"]
+    },
+    reportOnly: true,
+  })
+);
+
+app.use(compression());
+app.use(morgan('combined'));
+app.use(cookieParser(config.app.sessionSecret));
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({extended: false}));
+app.use(express.static(path.join(__dirname, 'public')));
+app.use((req, res, next) => {
+  next();
+});
+
+app.use(session({
+  resave: true,
+  saveUninitialized: true,
+  secret: config.app.sessionSecret
+}));
+app.use(flash());
+app.use(passport.initialize());
+app.use(passport.session());
+
+// caching disabled for every route
+// NOTE: Works in Firefox and Opera. Does not work in Edge
+app.use(function(req, res, next) {
+  res.set('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
+  next();
+});
+
+require('./routes/public')(app, config, lang);
+require('./routes/account')(app, config, passport, lang);
+
+// Handle 404
+app.use(function (req:any, res:any) {
+  res.status(404).render(lang+'/404')
+})
+
+// Handle 500 - any server error
+app.use(function (err:any, req:any, res:any, next:any) {
+  console.error(err.stack)
+  res.status(500).render(lang+'/500', {
+    error: err
+  })
+})
+
+app.listen(app.get('port'), function () {
+  console.log('Express server listening on port ' + app.get('port'));
+});
\ No newline at end of file
diff --git a/classes/project.js b/classes/project.ts
similarity index 63%
rename from classes/project.js
rename to classes/project.ts
index 85dafab3830e16ea3db1c50802a4a3a38e2988ed..045e86a73cad5333ba58bf85f9be8aa19fa619ea 100644
--- a/classes/project.js
+++ b/classes/project.ts
@@ -1,9 +1,16 @@
 class Project {
-    constructor(ownerGitlabId, id, name, desc, logo, path) {
+    ownerGitlabId:number
+    name:string
+    desc:string
+    id?:number
+    logo?:string
+    path?:string
+    
+    constructor(ownerGitlabId:number, name:string, desc:string, id?:number, logo?:string, path?:string) {
         this.ownerGitlabId = ownerGitlabId
-        this.id = id
         this.name = name
         this.desc = desc
+        this.id = id
         this.logo = logo
         this.path = path
     }
@@ -28,24 +35,24 @@ class Project {
         return this.path
     }
     // setter
-    setOwnerGitlabId(newOwnerGitlabId){
+    setOwnerGitlabId(newOwnerGitlabId:number){
         this.ownerGitlabId = newOwnerGitlabId
     }
-    setId(newId) {
+    setId(newId:number) {
         this.id = newId
     }
-    setName(newName) {
+    setName(newName:string) {
         this.name = newName
     }
-    setDesc(newDesc) {
+    setDesc(newDesc:string) {
         this.desc = newDesc
     }
-    setLogo(newLogoUrl) {
+    setLogo(newLogoUrl:string) {
         this.logo = newLogoUrl
     }
-    setPath(newPath) {
+    setPath(newPath:string) {
         this.path = newPath
     }
 }
 
-module.exports = Project
\ No newline at end of file
+export = Project
\ No newline at end of file
diff --git a/classes/repo.js b/classes/repo.js
deleted file mode 100644
index c99ac66f6e4ada393426c40df94c2a25335d96d1..0000000000000000000000000000000000000000
--- a/classes/repo.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const Project = require("./project");
-
-class Repo extends Project {
-    constructor(ownerGitlabId, id, name, desc, logo, path) {
-        super(ownerGitlabId, id, name, desc, logo, path)
-    }
-}
-
-module.exports = Repo
\ No newline at end of file
diff --git a/classes/repo.ts b/classes/repo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b41a8fe9ad343c385383d8ede7f1f82a57f6162f
--- /dev/null
+++ b/classes/repo.ts
@@ -0,0 +1,9 @@
+import Project from "./project"
+
+class Repo extends Project {
+    constructor(ownerGitlabId:number, name:string, desc:string, id?:number, logo?:string, path?:string) {
+        super(ownerGitlabId, name, desc, id, logo, path)
+    }
+}
+
+export = Repo
\ No newline at end of file
diff --git a/classes/user.js b/classes/user.js
deleted file mode 100644
index 94f07edd3f8c382b22504f0e356f84506011d662..0000000000000000000000000000000000000000
--- a/classes/user.js
+++ /dev/null
@@ -1,83 +0,0 @@
-class User {
-    constructor(id, email, salutation, title, firstName, lastName, industry, organisation, speciality, is_m4lab_idp, gitlabUserId, verificationStatus) {
-        this.id = id
-        this.email = email
-        this.salutation = salutation
-        this.title = title
-        this.firstName = firstName
-        this.lastName = lastName
-        this.industry = industry
-        this.organisation = organisation
-        this.speciality = speciality
-        this.is_m4lab_idp = is_m4lab_idp // 1 or 0
-        this.gitlabUserId = gitlabUserId
-        this.verificationStatus = verificationStatus
-    }
-
-    // getter
-    getId() {
-        return this.id
-    }
-    getEmail() {
-        return this.email
-    }
-    getFullName() {
-        return this.firstName+' '+this.lastName
-    }
-    getIdpStatus() {
-        return this.is_m4lab_idp
-    }
-    getGitlabUserId() {
-        return this.gitlabUserId
-    }
-    getVerificationStatus() {
-        return this.verificationStatus
-    }
-    // setter
-    setEmail(email) {
-        this.email = email
-    }
-    setSalutation(salutation) {
-        this.salutation = salutation
-    }
-    setTitle(title) {
-        this.title = title
-    }
-    setFirstName(firstName) {
-        this.firstName = firstName
-    }
-    setLastName(lastName) {
-        this.lastName = lastName
-    }
-    setIndustry(industry) {
-        this.industry = industry
-    }
-    setOrganisation(organisation) {
-        this.organisation = organisation
-    }
-    setSpeciality(speciality) {
-        this.speciality = speciality
-    }
-    setM4lab_idp(m4lab_idp) {
-        this.m4lab_idp = m4lab_idp
-    }
-    setGitlabUserId(newGitlabUserId) {
-        this.gitlabUserId = newGitlabUserId
-    }
-    setVerificationStatus(verificationStatus) {
-        this.verificationStatus = verificationStatus
-    }
-
-    updateProfile(newSalutation, newTitle, newFirstname, newLastname, newEmail, newOrganisation, newIndustry, newSpeciality) {
-        this.salutation = newSalutation
-        this.title = newTitle
-        this.firstName = newFirstname
-        this.lastName = newLastname
-        this.email = newEmail
-        this.organisation = newOrganisation
-        this.industry = newIndustry
-        this.speciality = newSpeciality
-    }
-}
-
-module.exports = User
\ No newline at end of file
diff --git a/classes/user.ts b/classes/user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3b26a694b4a95dd98109f976189561ff8a08a31d
--- /dev/null
+++ b/classes/user.ts
@@ -0,0 +1,97 @@
+class User {
+    id:number
+    email:string
+    salutation:string // should be enum
+    title:string // should be enum
+    firstName:string
+    lastName:string
+    industry:string
+    organisation:string
+    speciality:string
+    is_m4lab_idp:number // 1 or 0
+    verificationStatus:number // 1 or 0 - // should be boolean
+    gitlabUserId?:number
+
+    constructor(id:number, email:string, salutation:string, title:string, firstName:string, lastName:string, industry:string, organisation:string,
+        speciality:string, is_m4lab_idp:number, verificationStatus:number, gitlabUserId?:number) {
+            this.id = id
+            this.email = email
+            this.salutation = salutation
+            this.title = title
+            this.firstName = firstName
+            this.lastName = lastName
+            this.industry = industry
+            this.organisation = organisation
+            this.speciality = speciality
+            this.is_m4lab_idp = is_m4lab_idp
+            this.verificationStatus = verificationStatus
+            this.gitlabUserId = gitlabUserId
+    }
+
+    // getter
+    getId() {
+        return this.id
+    }
+    getEmail() {
+        return this.email
+    }
+    getFullName() {
+        return this.firstName+' '+this.lastName
+    }
+    getIdpStatus() {
+        return this.is_m4lab_idp
+    }
+    getVerificationStatus() {
+        return this.verificationStatus
+    }
+    getGitlabUserId() {
+        return this.gitlabUserId
+    }
+    // setter
+    setEmail(email:string) {
+        this.email = email
+    }
+    setSalutation(salutation:string) {
+        this.salutation = salutation
+    }
+    setTitle(title:string) {
+        this.title = title
+    }
+    setFirstName(firstName:string) {
+        this.firstName = firstName
+    }
+    setLastName(lastName:string) {
+        this.lastName = lastName
+    }
+    setIndustry(industry:string) {
+        this.industry = industry
+    }
+    setOrganisation(organisation:string) {
+        this.organisation = organisation
+    }
+    setSpeciality(speciality:string) {
+        this.speciality = speciality
+    }
+    setM4lab_idp(m4lab_idp:number) {
+        this.is_m4lab_idp = m4lab_idp
+    }
+    setVerificationStatus(verificationStatus:number) {
+        this.verificationStatus = verificationStatus
+    }
+    setGitlabUserId(newGitlabUserId:number) {
+        this.gitlabUserId = newGitlabUserId
+    }
+
+    updateProfile(newSalutation:string, newTitle:string, newFirstname:string, newLastname:string, newEmail:string, newOrganisation:string, newIndustry:string, newSpeciality:string) {
+        this.salutation = newSalutation
+        this.title = newTitle
+        this.firstName = newFirstname
+        this.lastName = newLastname
+        this.email = newEmail
+        this.organisation = newOrganisation
+        this.industry = newIndustry
+        this.speciality = newSpeciality
+    }
+}
+
+export = User
\ No newline at end of file
diff --git a/classes/website.js b/classes/website.js
deleted file mode 100644
index 1d05c40059221e15d8fa04fc43abee51d7e2190f..0000000000000000000000000000000000000000
--- a/classes/website.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const Project = require("./project");
-
-class Website extends Project {
-    constructor(ownerGitlabId, id, name, desc, logo, path) {
-        super(ownerGitlabId, id, name, desc, logo, path)
-    }
-}
-
-module.exports = Website
\ No newline at end of file
diff --git a/classes/website.ts b/classes/website.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bd64140dde3774db0aeaba750bd07691ac348059
--- /dev/null
+++ b/classes/website.ts
@@ -0,0 +1,9 @@
+import Project from "./project"
+
+class Website extends Project {
+    constructor(ownerGitlabId:number, name:string, desc:string, id?:number, logo?:string, path?:string) {
+        super(ownerGitlabId, name, desc, id, logo, path)
+    }
+}
+
+export = Website
\ No newline at end of file
diff --git a/config/config.js b/config/config.ts
similarity index 94%
rename from config/config.js
rename to config/config.ts
index e4bb457ce3bd4b6f30a784e4ec7d2dc685fba4b4..47558a5d53d2a00b17098074510779b5bb44cb05 100644
--- a/config/config.js
+++ b/config/config.ts
@@ -1,4 +1,4 @@
-module.exports = {
+export = {
   development: {
     app: {
       name: 'User Account Management',
@@ -28,7 +28,7 @@ module.exports = {
       host: 'mailhost',  // hostname
       secureConnection: false,        // TLS requires secureConnection to be false
       port: 587,                      // port for secure SMTP
-      TLS: true,                      // sets requireTLS
+      TLS: true,
       authUser: 'mailuser',
       authPass: 'mailpass',
       tlsCiphers: 'SSLv3',
@@ -67,7 +67,7 @@ module.exports = {
       host: 'mailhost',  // hostname
       secureConnection: false,        // TLS requires secureConnection to be false
       port: 587,                      // port for secure SMTP
-      TLS: true,                      // sets requireTLS
+      TLS: true,
       authUser: 'mailuser',
       authPass: 'mailpass',
       tlsCiphers: 'SSLv3',
@@ -77,4 +77,4 @@ module.exports = {
       token_readWriteProjects: 'token-goes-here'
     }
   }
-}
+}
\ No newline at end of file
diff --git a/config/const.js b/config/const.ts
similarity index 98%
rename from config/const.js
rename to config/const.ts
index dcbb821a4bf191c8a5ddd0dd10e9e0abab0a1c56..302d017701af834d7cf3f73f3b66c2e0a0d2f584 100644
--- a/config/const.js
+++ b/config/const.ts
@@ -1,4 +1,4 @@
-module.exports = {
+export = {
 
     mailSignature: 'Mit den besten Grüßen,<br/>das Transferportal-Team der HFT Stuttgart<br/><br/>' +
         'Transferportal der Hochschule für Technik Stuttgart<br/>' +
diff --git a/config/dbconn.js b/config/dbconn.ts
similarity index 91%
rename from config/dbconn.js
rename to config/dbconn.ts
index 670032958e099606b5558a39b94cc6492eb155e4..d918ce7c2e911d3a997c92df8d313f334f8024ca 100644
--- a/config/dbconn.js
+++ b/config/dbconn.ts
@@ -1,6 +1,6 @@
-const mysql = require('mysql')
+import mysql from 'mysql'
 
-var env = process.env.NODE_ENV || 'testing';
+var env = process.env.NODE_ENV || 'testing'
 const config = require('./config')[env]
 
 // ==== USER ACOOUNT DB CONNECTION ====
@@ -14,7 +14,7 @@ var userConnection = mysql.createConnection({
 })
 
 userConnection.connect(function(err) {
-    if (err) throw err;
+    if (err) throw err
 })
 userConnection.query('USE '+config.database.dbUser)
 
@@ -52,7 +52,7 @@ var projectConnection = mysql.createConnection({
 })
 
 projectConnection.connect(function(err) {
-    if (err) throw err;
+    if (err) throw err
 })
 projectConnection.query('USE '+config.database.dbProject)
 
@@ -61,4 +61,4 @@ var connection = {
     project: projectConnection
 }
 
-module.exports = connection
\ No newline at end of file
+export = connection
\ No newline at end of file
diff --git a/config/dbconn2.js b/config/dbconn2.ts
similarity index 91%
rename from config/dbconn2.js
rename to config/dbconn2.ts
index abbd0a012666e0d1f86b03512759cd438cd2d8fe..c13c40f11c2c3994791d75c866c5cfc6d210e1d7 100644
--- a/config/dbconn2.js
+++ b/config/dbconn2.ts
@@ -1,6 +1,6 @@
-const mysql = require('mysql2')
+import mysql from 'mysql2'
 
-var env = process.env.NODE_ENV || 'testing';
+var env = process.env.NODE_ENV || 'testing'
 const config = require('./config')[env]
 
 // ==== USER ACOOUNT DB CONNECTION ====
@@ -14,7 +14,7 @@ var userConnection = mysql.createConnection({
 })
 
 userConnection.connect(function(err) {
-    if (err) throw err;
+    if (err) throw err
 })
 userConnection.query('USE '+config.database.dbUser)
 
@@ -52,7 +52,7 @@ var projectConnection = mysql.createConnection({
 })
 
 projectConnection.connect(function(err) {
-    if (err) throw err;
+    if (err) throw err
 })
 projectConnection.query('USE '+config.database.dbProject)
 
@@ -61,4 +61,4 @@ var connection = {
     project: projectConnection
 }
 
-module.exports = connection
\ No newline at end of file
+export = connection
\ No newline at end of file
diff --git a/config/mailer.js b/config/mailer.js
deleted file mode 100644
index d7c6faf0983428c4e15944cf5d85fa68ee5c158f..0000000000000000000000000000000000000000
--- a/config/mailer.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const nodemailer = require('nodemailer');
-const nodemailerNTLMAuth = require('nodemailer-ntlm-auth');
-
-
-var env = process.env.NODE_ENV || 'testing';
-const config = require('./config')[env]
-
-var smtpTransport = nodemailer.createTransport({
-    host: config.mailer.host,
-    secure: config.mailer.secureConnection,
-    port: config.mailer.port,
-    requireTLS: config.mailer.TLS,
-    auth: {
-      type: 'custom',
-      method: 'NTLM',
-      user: config.mailer.authUser,
-      pass: config.mailer.authPass,
-     options: {
-        domain: 'ad'
-      }
-    },
-    customAuth:{
-        NTLM: nodemailerNTLMAuth
-    }
-});
-  
-var mailOptions = {
-    to: "",
-    from: config.mailer.from,
-    subject: "",
-    text: ""
-};
-
-var mailer = {
-    transport: smtpTransport,
-    options: mailOptions
-}
-
-module.exports = mailer
diff --git a/config/mailer.ts b/config/mailer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..18f25191d2a4abb7e30f6810404e0968a1660a4c
--- /dev/null
+++ b/config/mailer.ts
@@ -0,0 +1,40 @@
+const nodemailer = require('nodemailer')
+const nodemailerNTLMAuth = require('nodemailer-ntlm-auth')
+
+var env = process.env.NODE_ENV || 'testing'
+const config = require('./config')[env]
+
+var smtpTransporter = nodemailer.createTransport({
+  host: config.mailer.host,
+  secure: config.mailer.secureConnection,
+  port: config.mailer.port,
+  requireTLS: config.mailer.TLS,
+  auth: {
+    type: 'custom',
+    method: 'NTLM',
+    user: config.mailer.authUser,
+    pass: config.mailer.authPass,
+    options: {
+      domain: 'ad'
+    }
+  },
+  customAuth:{
+    NTLM: nodemailerNTLMAuth
+  }
+});
+
+var mailOptions:any = {
+    to: "",
+    cc: "",
+    from: config.mailer.from,
+    subject: "",
+    text: "",
+    html: ""
+}
+
+var mailer:any = {
+    transporter: smtpTransporter,
+    options: mailOptions
+}
+
+export = mailer
\ No newline at end of file
diff --git a/functions/gitlab.js b/functions/gitlab.ts
similarity index 58%
rename from functions/gitlab.js
rename to functions/gitlab.ts
index 62ff36508f80a0747538386a7838e4892c5a1706..5924afd12edb9abca93fef917957dada166078f4 100644
--- a/functions/gitlab.js
+++ b/functions/gitlab.ts
@@ -1,13 +1,12 @@
+import axios from 'axios'
+import fs from 'fs'
+import formData from 'form-data'
+
 var env = process.env.NODE_ENV || 'testing'
 const config = require('../config/config')[env]
-const axios = require('axios')
-const fs = require('fs')
-var formData = require('form-data')
 
 var gitlab = {
-    // todo: GraphQL currentUser
-
-    getUserByEmail: async function(email) {
+    getUserByEmail: async function(email:string) {
         return axios({
             method: 'get',
             url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/users?search='+email,
@@ -15,9 +14,12 @@ var gitlab = {
                 'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects}
         })
         .then(res => res.data[0])
-        .catch(err => console.error(err))
+        .catch(function(err){
+            console.error(err)
+            return null
+        })
     },
-    createNewPages: async function(newPagesData, newLogoFile, template) {
+    createNewPages: async function(newPagesData:any, newLogoFile:string, template:any) {
         let data = new formData()
         data.append('avatar', fs.createReadStream(newLogoFile))
 
@@ -32,16 +34,15 @@ var gitlab = {
             },
             data: data
         })
-        .then(res => res = {
-            error: false,
-            data: res.data
-        })
-        .catch(err => res = {
-            error: true,
-            data: err.response.data
+        .then(res => res.data)
+        .catch(function(err) {
+            console.error("ERR Status: "+err.response.status)
+            console.error("ERR Name: "+err.response.data.message.name)
+            console.error("ERR Path: "+err.response.data.message.path)
+            return err.response
         })
     },
-    updateProject: async function(updatedProjectData, newLogoFile){
+    updateProject: async function(updatedProjectData:any, newLogoFile:string){
         let data = new formData()
         if (newLogoFile) {
             data.append('avatar', fs.createReadStream(newLogoFile))
@@ -57,16 +58,16 @@ var gitlab = {
             },
             data : data
         })
-        .then(res => res = {
-            error: false,
-            data: res.data
-        })
-        .catch(err => res = {
-            error: true,
-            data: err.response.data
+        //.then(res => res.data[0])
+        .then(res => res.data)
+        .catch(function(err){
+            console.error("ERR Status: "+err.response.status)
+            console.error("ERR Name: "+err.response.data.message.name)
+            console.error("ERR Path: "+err.response.data.message.path)
+            return err.response
         })
     },
-    deleteProjectById: function(projectId){
+    deleteProjectById: function(projectId:number){
         // https://docs.gitlab.com/ee/api/projects.html#delete-project
         return axios({
             method: 'delete',
@@ -75,16 +76,15 @@ var gitlab = {
                 'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects 
             }
         })
-        .then(res => res = {
-            error: false,
-            data: res.data
-        })
-        .catch(err => res = {
-            error: true,
-            data: err.response.data
+        .then(res => true)
+        .catch(function(err) {
+            console.error("ERR Status: "+err.response.status)
+            console.error("ERR Name: "+err.response.data.message.name)
+            console.error("ERR Path: "+err.response.data.message.path)
+            return false
         })
     },
-    getUserProjects: async function(gitlabUserId) {
+    getUserProjects: async function(gitlabUserId:number) {
         return axios({
             method: 'get',
             url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/users/'+gitlabUserId+'/projects?owned=true&visibility=public',
@@ -93,9 +93,12 @@ var gitlab = {
             }
         })
         .then(res => res.data)
-        .catch(err => console.error(err))
+        .catch(function(err) {
+            console.error(err)
+            return null
+        })
     },
-    getProjectById: async function(projectId) {
+    getProjectById: async function(projectId:number) {
         return axios({
             method: 'get',
             url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+projectId,
@@ -104,45 +107,22 @@ var gitlab = {
             }
         })
         .then(res => res.data)
-        .catch(err => console.error(err.response.status))
+        .catch(function(err) {
+            console.error(err)
+            return null
+        })
     },
-    getProjectPipelineLatestStatus: async function(projectId) {
+    getProjectPipelineLatestStatus: async function(projectId:number) {
         return axios({
             method: 'get',
             url: 'https://transfer.hft-stuttgart.de/gitlab/api/v4/projects/'+projectId+'/pipelines'
         })
         .then(res => res.data[0].status)
-        .catch(err => console.error(err))
-    },
-    //
-    // test GraphQL
-    getGraphqlTest: function(callback) {
-        axios({
-            url: 'https://gitlab.com/api/graphql',
-            method: 'get',
-            headers: {
-                'Content-Type': 'application/json',
-                'Authorization': 'Bearer '+config.gitlab.token_readWriteProjects
-            },
-            data: {
-                query: `{
-                    currentUser {
-                        id
-                        username
-                    }
-                }`
-            /*  query: `{
-                projects {
-                    nodes {
-                        id
-                    }
-                }
-              }` */
-            }
-        }).then((result) => {
-            console.log(JSON.stringify(result.data))
-        });
+        .catch(function(err) {
+            console.error(err)
+            return null
+        })
     }
 }
 
-module.exports = gitlab
\ No newline at end of file
+export = gitlab
\ No newline at end of file
diff --git a/functions/helpers.js b/functions/helpers.ts
similarity index 69%
rename from functions/helpers.js
rename to functions/helpers.ts
index 4645aec75363bf4110ce33f65b8615dc60902f60..1c3451fc00883bf4307ba324dc98f75a7d76b80f 100644
--- a/functions/helpers.js
+++ b/functions/helpers.ts
@@ -1,5 +1,5 @@
 var helpers = {
-    stringToArray: function (input){
+    stringToArray: function (input:string){
         if(input != null){
             return input.split(',');
         }else{
@@ -8,4 +8,4 @@ var helpers = {
     }
 };
 
-module.exports = helpers;
\ No newline at end of file
+export = helpers;
\ No newline at end of file
diff --git a/functions/methods.js b/functions/methods.ts
similarity index 56%
rename from functions/methods.js
rename to functions/methods.ts
index 0037a7e143bab55cee0d9d48b71263818af86b5a..16143b851a743a4f5e023c4b50913dd695cbcc2b 100644
--- a/functions/methods.js
+++ b/functions/methods.ts
@@ -1,57 +1,55 @@
-const dbconn_OBSOLETE = require('../config/dbconn') // DO NOT USE THIS FOR NEW FUNCTIONS
-const dbconn = require('../config/dbconn2')
+import dbconn_OBSOLETE = require('../config/dbconn') // DO NOT USE THIS FOR NEW FUNCTIONS
+import dbconn = require('../config/dbconn2')
 
 var methods = {
     // ===================== user db =====================
-    registerNewUser: function(data, callback) {
-        dbconn_OBSOLETE.user.beginTransaction(function(err) { // START TRANSACTION
-            if (err) {
-                throw err
-            }
+    registerNewUser: function(data:any, callback:any) {
+        dbconn_OBSOLETE.user.beginTransaction(function(err:any) { // START TRANSACTION
+            if (err) { throw err }
             // insert profile
-            dbconn_OBSOLETE.user.query('INSERT INTO user SET ?', data.profile, function (err, results, fields) {
+            dbconn_OBSOLETE.user.query('INSERT INTO user SET ?', data.profile, function (err:any, results:any, fields:any) {
                 if (err) {
                   return dbconn_OBSOLETE.user.rollback(function() {
                     throw err
                   });
                 }
-                var newUserId = results.insertId
+                let newUserId:number = results.insertId
                 // set password
-                var credentialData = {
+                var credentialData:any = {
                     user_id: newUserId,
                     password: data.password
                 }
-                dbconn_OBSOLETE.user.query('INSERT INTO credential SET ?', credentialData, function (err, results, fields) {
+                dbconn_OBSOLETE.user.query('INSERT INTO credential SET ?', credentialData, function (err:any, results:any, fields:any) {
                     if (err) {
                         return dbconn_OBSOLETE.user.rollback(function() {
                             throw err
                         });
                     }
                     // set default user-project-role
-                    var projectRoleData = {
+                    var projectRoleData:any = {
                         project_id: 1,  //M4_LAB
                         role_id: 2,     // USER
                         user_id: newUserId
                     }
-                    dbconn_OBSOLETE.user.query('INSERT INTO user_project_role SET ?', projectRoleData, function (err, results, fields) {
+                    dbconn_OBSOLETE.user.query('INSERT INTO user_project_role SET ?', projectRoleData, function (err:any, results:any, fields:any) {
                         if (err) {
                             return dbconn_OBSOLETE.user.rollback(function() {
                                 throw err
                             });
                         }
                         // MLAB-129: INSERT verification token
-                        let verificationData = {
+                        let verificationData:any = {
                             user_id: newUserId,
                             token: data.verificationToken
                         }
-                        dbconn_OBSOLETE.user.query('INSERT INTO verification SET ?', verificationData, function (err, results, fields) {
+                        dbconn_OBSOLETE.user.query('INSERT INTO verification SET ?', verificationData, function (err:any, results:any, fields:any) {
                             if (err) {
                                 return dbconn_OBSOLETE.user.rollback(function() {
                                     throw err
                                 });
                             }
                             // COMMIT
-                            dbconn_OBSOLETE.user.commit(function(err) {
+                            dbconn_OBSOLETE.user.commit(function(err:any) {
                                 if (err) {
                                     return dbconn_OBSOLETE.user.rollback(function() {
                                         throw err
@@ -65,9 +63,9 @@ var methods = {
             callback(err)
         })
     },
-    getUserByEmail: async function(email) {
+    getUserByEmail: async function(email:any) {
         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+'"')
+            let rows:any = await dbconn.user.promise().query('SELECT id, verificationStatus, salutation, title, firstname, lastname, industry, organisation, speciality, m4lab_idp FROM user WHERE email = "' +email+'"')
             if (rows[0][0]) {
                 return rows[0][0]
             }
@@ -77,9 +75,9 @@ var methods = {
         }
         return null
     },
-    getUserEmailById: async function(userId) {
+    getUserEmailById: async function(userId:number) {
         try {
-            let rows = await dbconn.user.promise().query('SELECT email FROM user WHERE id = ' +userId)
+            let rows:any = await dbconn.user.promise().query('SELECT email FROM user WHERE id = ' +userId)
             if (rows[0][0]) {
                 return rows[0][0].email
             }
@@ -89,9 +87,9 @@ var methods = {
         }
         return null
     },
-    checkUserEmail: async function(email) {
+    checkUserEmail: async function(email:any) {
         try {
-            let rows = await dbconn.user.promise().query('SELECT id, email FROM user WHERE email = "' +email+'"')
+            let rows:any = await dbconn.user.promise().query('SELECT id, email FROM user WHERE email = "' +email+'"')
             if (rows[0][0]) {
                 return rows[0][0]
             }
@@ -101,9 +99,9 @@ var methods = {
         }
         return null
     },
-    getUserByToken: async function(token) {
+    getUserByToken: async function(token:any) {
         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 = "'
+            let rows:any = 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]
@@ -114,47 +112,38 @@ var methods = {
         }
         return null
     },
-	updateUserById: function(userData, callback) {
-		dbconn_OBSOLETE.user.query('UPDATE user SET ? WHERE id = ' +userData.id, userData, function (err, rows, fields) {
-            if (err) throw err
-            callback(err)
-        })
-    },
-    updateCredential: function(data, callback) {
-        dbconn_OBSOLETE.user.query('UPDATE credential SET ? WHERE user_id = ' +data.user_id, data, function (err, rows, fields) {
-            if (err) throw err
-            callback(err)
-        })
+    updateUserById: async function(userId:number, userData:any) {
+        try {
+            let result:any = await dbconn.user.promise().query('UPDATE user SET ? WHERE id = ' +userId, userData)
+            return result
+        } catch (err) {
+            console.error(err)
+        }
+        return null
     },
-    getUserIdByEmail_OBSOLETE: function(email, callback) {
-        let userId
-        dbconn_OBSOLETE.user.query('SELECT id FROM user WHERE email = "' +email+'"', function (err, rows, fields) {
-            if (err) {
-                throw err
-            }
-            else {
-                if ( rows.length > 0) {
-                    userId = rows[0].id
-                }
-            }
-            callback(userId, err)
-        });
+    updateCredential: async function(data:any) {
+        try {
+            let result:any = await dbconn.user.promise().query('UPDATE credential SET ? WHERE user_id = ' +data.user_id, data)
+            return result
+        } catch (err) {
+            console.error(err)
+        }
+        return null
     },
-    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) {
+    addUserProjectRole_OBSOLETE: function(data:any, callback:any) {
+        /*
+        dbconn_OBSOLETE.user.query('INSERT INTO user_project_role SET ?', data, function (err:any, results:any, fields:any){
             if (err) throw err
-            callback(rows, err)
-        });
-    },
-    addUserProjectRole: function(data, callback) {
-        dbconn_OBSOLETE.user.query('INSERT INTO user_project_role SET ?', data, function (err, results, fields){
+            callback(err)
+        }) */
+        dbconn.user.query('INSERT INTO user_project_role SET ?', data, function (err:any){
             if (err) throw err
             callback(err)
         })
     },
-    getVerificationTokenByUserId: async function(userId) {
+    getVerificationTokenByUserId: async function(userId:number) {
         try {
-            let rows = await dbconn.user.promise().query('SELECT token FROM verification WHERE user_id = "' +userId+'"')
+            let rows:any = await dbconn.user.promise().query('SELECT token FROM verification WHERE user_id = "' +userId+'"')
             if (rows[0][0]) {
                 return rows[0][0].token
             }
@@ -164,9 +153,9 @@ var methods = {
         }
         return null
     },
-    getUserIdByVerificationToken: async function(token) {
+    getUserIdByVerificationToken: async function(token:any) {
         try {
-            let rows = await dbconn.user.promise().query('SELECT user_id FROM verification WHERE token = "' +token+'"')
+            let rows:any = await dbconn.user.promise().query('SELECT user_id FROM verification WHERE token = "' +token+'"')
             if (rows[0][0]) {
                 return rows[0][0].user_id
             }
@@ -178,21 +167,21 @@ var methods = {
         }
         return null
     },
-    verifyUserAccount: function(userData, callback) {
-        dbconn_OBSOLETE.user.beginTransaction(function(err) { // START TRANSACTION
+    verifyUserAccount: function(userData:any, callback:any) {
+        dbconn_OBSOLETE.user.beginTransaction(function(err:any) { // START TRANSACTION
             if (err) { throw err }
             // update user status
-            dbconn_OBSOLETE.user.query('UPDATE user SET ? WHERE id =' +userData.id, userData, function (err, rows, fields) {
+            dbconn_OBSOLETE.user.query('UPDATE user SET ? WHERE id =' +userData.id, userData, function (err:any, rows:any, fields:any) {
                 if (err) {
                     return dbconn_OBSOLETE.user.rollback(function() { throw err })
                 }
                 // delete verification token
-                dbconn_OBSOLETE.user.query('DELETE FROM verification WHERE user_id = '+userData.id, function (err, rows, fields) {
+                dbconn_OBSOLETE.user.query('DELETE FROM verification WHERE user_id = '+userData.id, function (err:any, rows:any, fields:any) {
                     if (err) {
                         return dbconn_OBSOLETE.user.rollback(function() { throw err })
                     }
                     // COMMIT
-                    dbconn_OBSOLETE.user.commit(function(err) {
+                    dbconn_OBSOLETE.user.commit(function(err:any) {
                         if (err) {
                             return dbconn_OBSOLETE.user.rollback(function() { throw err })
                         }
@@ -203,9 +192,9 @@ var methods = {
         })
     },
     /* ===== GitLab ===== */
-    getGitlabId: async function(userId) {
+    getGitlabId: async function(userId:number) {
         try {
-            let rows = await dbconn.user.promise().query('SELECT gu.gitlab_userId FROM user_gitlab gu, user u WHERE u.id = "' +userId+'" and gu.user_id = u.id')
+            let rows:any = await dbconn.user.promise().query('SELECT gu.gitlab_userId FROM user_gitlab gu, user u WHERE u.id = "' +userId+'" and gu.user_id = u.id')
             if (rows[0][0]) {
                 return rows[0][0].gitlab_userId
             } else {
@@ -217,12 +206,12 @@ var methods = {
             return err
         }
     },
-    addGitlabUser: function(data, callback){
-        dbconn_OBSOLETE.user.query('INSERT INTO user_gitlab SET ?', data, function (err) {
+    addGitlabUser: function(data:any, callback:any){
+        dbconn.user.query('INSERT INTO user_gitlab SET ?', data, function (err:any) {
             if (err) throw err
             callback(err)
         })
     }
 };
 
-module.exports = methods;
\ No newline at end of file
+export = methods
\ No newline at end of file
diff --git a/public/js/jquery-ui/i18n/datepicker-de.js b/public/js/jquery-ui/i18n/datepicker-de.js
deleted file mode 100644
index e2e61d27b6b4bf33c0fd59e9ebf2d307d0337af3..0000000000000000000000000000000000000000
--- a/public/js/jquery-ui/i18n/datepicker-de.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* German initialisation for the jQuery UI date picker plugin. */
-/* Written by Milian Wolff (mail@milianw.de). */
-( function( factory ) {
-	if ( typeof define === "function" && define.amd ) {
-
-		// AMD. Register as an anonymous module.
-		define( [ "../widgets/datepicker" ], factory );
-	} else {
-
-		// Browser globals
-		factory( jQuery.datepicker );
-	}
-}( function( datepicker ) {
-
-datepicker.regional.de = {
-	closeText: "Schließen",
-	prevText: "&#x3C;Zurück",
-	nextText: "Vor&#x3E;",
-	currentText: "Heute",
-	monthNames: [ "Januar","Februar","März","April","Mai","Juni",
-	"Juli","August","September","Oktober","November","Dezember" ],
-	monthNamesShort: [ "Jan","Feb","Mär","Apr","Mai","Jun",
-	"Jul","Aug","Sep","Okt","Nov","Dez" ],
-	dayNames: [ "Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag" ],
-	dayNamesShort: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
-	dayNamesMin: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
-	weekHeader: "KW",
-	dateFormat: "dd.mm.yy",
-	firstDay: 1,
-	isRTL: false,
-	showMonthAfterYear: false,
-	yearSuffix: "" };
-datepicker.setDefaults( datepicker.regional.de );
-
-return datepicker.regional.de;
-
-} ) );
\ No newline at end of file
diff --git a/routes/account.js b/routes/account.js
deleted file mode 100644
index 0f3b2fc7fb77929caa72ef75797173fcecfa3a4d..0000000000000000000000000000000000000000
--- a/routes/account.js
+++ /dev/null
@@ -1,568 +0,0 @@
-const fs = require('fs')
-const SamlStrategy = require('passport-saml').Strategy
-const dbconn = require('../config/dbconn')
-const methods = require('../functions/methods')
-const gitlab = require('../functions/gitlab')
-const constants = require('../config/const')
-// pwd encryption
-const bcrypt = require('bcryptjs');
-const saltRounds = 10;
-const salt = 64; // salt length
-// forgot pwd
-const async = require('async')
-const crypto = require('crypto')
-const mailer = require('../config/mailer')
-const logoDir = 'public/upload/'
-const defaultLogo = 'public/default/logo.png'
-const tpGitlabURL = 'https://transfer.hft-stuttgart.de/gitlab/'
-const tpGitlabPagesURL = 'https://transfer.hft-stuttgart.de/pages/'
-
-const portalUser = require('../classes/user')
-const projectInformation = require('../classes/website')
-const projectRepo = require('../classes/repo')
-
-module.exports = function (app, config, passport, lang) {
-
-  // =========== PASSPORT =======
-  passport.serializeUser(function (user, done) {
-    done(null, user);
-  });
-
-  passport.deserializeUser(function (user, done) {
-    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: null,
-      
-      // 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, done) {
-    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, res) {
-      res.redirect('/account/');
-    }
-  );
-
-  // to generate Service Provider's XML metadata
-  app.get('/saml/metadata',
-    function(req, res) {
-      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) {
-    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, null, user.verificationStatus
-      )
-      
-      let userGitlabId = await methods.getGitlabId(loggedInUser.id)
-      if (userGitlabId) {
-        loggedInUser.setGitlabUserId(userGitlabId)
-      }
-      return loggedInUser
-    }
-  }
-
-  app.get('/', async function (req, res) {
-    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, res) {
-    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, uri) {
-      req.logout();
-
-      if ( req.session ) {
-        req.session.destroy((err) => {
-          if(err) {
-              return console.log(err);
-          }
-        });
-      }
-
-      return res.redirect(uri);
-    });
-  });
-
-  app.get('/profile', async function (req, res) {
-    if ( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      if(loggedInUser.getVerificationStatus() != 1) {
-        res.redirect('/account/')
-      } else {
-        res.render(lang+'/account/profile', {
-          user: loggedInUser
-        })
-      }
-    }
-  })
-
-  app.get('/services', async function(req, res){
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      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" })
-          }
-          
-          for (project in userProjects) {
-            if (userProjects[project].tag_list.includes('website')) {
-              let page = {
-                projectInformation: new projectInformation(loggedInUser.getGitlabUserId(), userProjects[project].id, userProjects[project].name,
-                  userProjects[project].description, 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].id, userProjects[project].name,
-                userProjects[project].description, 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}
-            // RS: update to await?
-            methods.addGitlabUser(gitlabActivationData, function(err){
-              if(err) {
-                res.status(500).render(lang+'/500', { error: err })
-              } else {
-                res.redirect('/account/services')
-              }
-            })
-          }
-        }
-      }
-    }
-  })
-
-  app.get('/security', async function (req, res) {
-    if ( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      if(loggedInUser.getVerificationStatus() == 1 && loggedInUser.getIdpStatus() == 1) {
-        res.render(lang+'/account/security', {
-          user: loggedInUser
-        })
-      } else {
-        res.redirect('/account/')
-      }
-    }
-  })
-
-  app.post('/updateProfile', async function (req, res) {
-    var 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,
-    }
-
-    if ( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      if (userData.email) {
-        dbconn.user.query('UPDATE user SET ? WHERE email = "' +userData.email+'"', userData, function (err, rows, fields) {
-            if (err) {
-              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('/changePwd', async function (req, res) {
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-
-      var currPwd = req.body.inputCurrPwd
-      var newPwd = req.body.inputNewPwd
-      var retypePwd = req.body.inputConfirm
-
-      // update - get userId from loggedInUser
-      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, function(err, hash) {
-                  var credentialData = {
-                    password: hash,
-                    user_id: userId
-                  }
-                  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!")
-                      mailer.options.to = req.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('/account/security')
-                  })
-                });
-              });
-            }
-          }
-        })
-      })
-    }
-  });
-  
-  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
-            }
-          })
-          res.send(true)
-        }
-      }
-    }
-  })
-
-  // ============= NEW GITLAB PAGES ===========================
-  
-  app.get('/newInformation', async function(req, res){
-    if ( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      let gitlabUser = await gitlab.getUserByEmail(loggedInUser.getEmail())
-      if (!gitlabUser) { // no user found
-        res.redirect('/account/services')
-      } else {
-        res.render(lang+'/account/newInformation', {
-          user: loggedInUser,
-          gitlabUsername: gitlabUser.username
-        })
-      }
-    }
-  })
-  app.post('/newInformation', async function(req, res) {
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-
-      if (!req.body.name && !req.body.description) {
-        res.flash('error', 'Bitte geben Sie die benötigten Daten ein')
-        res.redirect('/account/newInformation')
-      } else {
-        let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
-        let projectDesc = req.body.description
-        let projectTemplate = req.body.template
-        let newInformation = new projectInformation(loggedInUser.getGitlabUserId(), null, projectName, projectDesc, null, null)
-        let newLogoFile = defaultLogo
-          
-        if (req.files) { newLogoFile = req.files.logo }
-
-        async.waterfall([
-          function(callback){ // upload logo
-            if (!req.files) {
-              callback(null, newLogoFile)
-            } else {
-              newLogoFile.mv(logoDir + newLogoFile.name, function(err) {
-                newLogoFile = logoDir+newLogoFile.name
-                callback(err, newLogoFile)
-              })
-            }
-          },
-          async function(newLogoFile){ // create a new GitLab Page
-            let newPages = await gitlab.createNewPages(newInformation, newLogoFile, projectTemplate)
-            if (newPages.error) {
-              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.")
-              } else {
-                res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
-              }
-              res.redirect('/account/newInformation')
-            } else {
-              let newPagesData = newPages.data
-        
-              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.")
-              /* res.flash("success", "Your website will be published AFTER you complete your website by following the provided guideline below."+
-                "\r\n Your website URL: "+tpGitlabPagesURL+newPagesData.path_with_namespace+"/home/") */
-              res.redirect('/account/updateInformation?id='+newPagesData.id)
-            }
-          }
-        ], function (err) {
-          if(err) console.log(err)
-          // remove logo
-          if (req.files) {
-            fs.unlink(newLogoFile, (err) => {
-              if(err) console.log(err)
-            })
-          }
-        })
-      }
-    }
-  })
-
-  app.get('/updateInformation', async function(req, res){
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-
-      if(!req.query.id) {
-        res.redirect('/account/services')
-      } else {
-        let project = await gitlab.getProjectById(req.query.id)
-        if (!project) {
-          console.log(" ========= Error or no project found")
-          res.redirect('/account/services')
-        } else if (!project.owner) {
-          console.log(" ========= Project cannot be accessed, since it does not have an owner")
-          res.redirect('/account/services')
-        } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
-          console.log(" ========= Access denied: Not your project")
-          res.redirect('/account/services')
-        } else {
-          let curInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, project.name, project.description,
-            project.avatar_url, project.path_with_namespace)
-          
-          res.render(lang+'/account/updateInformation', {
-            user: loggedInUser,
-            information: curInformation
-          })
-        }
-      }
-    }
-  })
-  // update a website
-  app.post('/updateInformation', async function(req, res){
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-
-      if (!req.body.name && !req.body.description) {
-        res.flash('error', 'Bitte geben Sie die benötigten Daten ein')
-        res.redirect('/account/updateInformation')
-      } else {
-        let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
-        let projectDesc = req.body.description
-        let updatedInformation = new projectInformation(loggedInUser.getGitlabUserId(), req.query.id, projectName, projectDesc, null, null)
-        let newLogoFile
-
-        async.waterfall([
-          function(callback){ // upload logo
-            if(!req.files) {
-              callback(null, newLogoFile)
-            } else {
-              newLogoFile = req.files.logo
-              newLogoFile.mv(logoDir + newLogoFile.name, function(err) {
-                newLogoFile = logoDir + newLogoFile.name
-                callback(err, newLogoFile)
-              })
-            }
-          },
-          async function(newLogoFile, callback){ // update gitlab page
-            let updatedPages = await gitlab.updateProject(updatedInformation, newLogoFile)
-            let pagesData = updatedPages.data
-            if (updatedPages.error) {
-              if(pagesData.message.name == "has already been taken") {
-                res.flash("error", "Der Projektname ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
-              } else {
-                res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
-              }
-            } else {
-              updatedInformation.setLogo(pagesData.avatar_url)
-              updatedInformation.setPath(pagesData.path)
-              res.flash("success", "Ihre Website wurde aktualisiert")
-            }
-            res.redirect('/account/updateInformation?id='+updatedInformation.getId())
-          }
-        ], function (err) {
-          if(err) console.log(err)
-          if(newLogoFile){ // remove logo
-            fs.unlink(newLogoFile, (err) => {
-              if(err) console.log(err)
-            })
-          }
-        })
-      }
-    }
-  })
-
-  app.delete('/deleteProject', async function(req, res){
-    console.log("delete project")
-
-    if( !req.isAuthenticated() ) {
-      res.redirect('/login')
-    } else {
-      let loggedInUser = await getLoggedInUserData(req.user.email)
-      let projectId = req.body.id
-
-      if (projectId) {
-        // check if the owner is valid
-        let project = await gitlab.getProjectById(projectId)
-        if (!project) {
-          console.log(" ========= Error or no project found")
-        } else if (!project.owner) {
-          console.log(" ========= Project cannot be accessed, since it does not have an owner")
-        } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
-          console.log(" ========= Access denied: Not your project")
-        } else {
-          // delete project
-          let project = await gitlab.deleteProjectById(projectId)
-          if (project.error) {
-            res.flash("error", "Project cannot be deleted. Please try again.")
-          }
-        }
-      }
-      res.redirect('/account/services')
-    }
-  })
-
-}
\ No newline at end of file
diff --git a/routes/account.ts b/routes/account.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da1b2fb9e4907cfb424dc8edd6ae085be6beba37
--- /dev/null
+++ b/routes/account.ts
@@ -0,0 +1,596 @@
+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+'<div>'+constants.mailSignature+'</div>'
+                      mailer.transporter.sendMail(mailer.options, function(err:any) {
+                        if (err) { console.log(err) }
+                      })
+                    }
+                    res.redirect('/account/security')
+
+                  });
+                });
+              }
+            }
+          })
+        })
+      }
+    }
+  });
+  
+  app.get('/resendVerificationEmail', async function(req:any, res:any){
+    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:any) {
+            if (err) {
+              console.log('cannot send email')
+              throw err
+            }
+          })
+          res.send(true)
+        }
+      }
+    }
+  })
+
+  // ============= NEW GITLAB PAGES ===========================
+  
+  app.get('/newInformation', async function(req:any, res:any){
+    if ( !req.isAuthenticated() ) {
+      res.redirect('/login')
+    } else {
+      let loggedInUser = await getLoggedInUserData(req.user.email)
+      if (!loggedInUser) {
+        res.redirect('/login')
+      } else {
+        let gitlabUser = await gitlab.getUserByEmail(loggedInUser.getEmail())
+        if (!gitlabUser) { // no user found
+          res.redirect('/account/services')
+        } else {
+          res.render(lang+'/account/newInformation', {
+            user: loggedInUser,
+            gitlabUsername: gitlabUser.username
+          })
+        }
+      }
+    }
+  })
+  app.post('/newInformation', async function(req:any, res:any) {
+    if( !req.isAuthenticated() ) {
+      res.redirect('/login')
+    } else {
+      let loggedInUser = await getLoggedInUserData(req.user.email)
+      if (!loggedInUser) {
+        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 {
+          let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
+          let projectDesc = req.body.description
+          let projectTemplate = req.body.template
+          let newInformation = new projectInformation(loggedInUser.getGitlabUserId()!, projectName, projectDesc)
+          let newLogoFile = defaultLogo
+            
+          if (req.files) { newLogoFile = req.files.logo }
+  
+          async.waterfall([
+            function(callback:any){ // upload logo
+              if (!req.files) {
+                callback(null, newLogoFile)
+              } else {
+                newLogoFile.mv(logoDir + newLogoFile.name, function(err:any) {
+                  newLogoFile = logoDir+newLogoFile.name
+                  callback(err, newLogoFile)
+                })
+              }
+            },
+            async function(newLogoFile:any){ // create a new GitLab Page
+              let newPages = await gitlab.createNewPages(newInformation, newLogoFile, projectTemplate)
+              if (newPages.status) {
+                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.")
+                } else {
+                  res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
+                }
+                res.redirect('/account/newInformation')
+              } else {
+                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.")
+                res.redirect('/account/updateInformation?id='+newPages.id)
+              }
+            }
+          ], function (err) {
+            if(err) console.log(err)
+            // remove logo
+            if (req.files) {
+              fs.unlink(newLogoFile, (err) => {
+                if(err) console.log(err)
+              })
+            }
+          })
+        }
+      }
+    }
+  })
+
+  app.get('/updateInformation', async function(req:any, res:any){
+    if( !req.isAuthenticated() ) {
+      res.redirect('/login')
+    } else {
+      let loggedInUser = await getLoggedInUserData(req.user.email)
+
+      if (!loggedInUser) {
+        res.redirect('/login')
+      } else {
+        if(!req.query.id) {
+          res.redirect('/account/services')
+        } else {
+          let project = await gitlab.getProjectById(req.query.id)
+          if (!project) {
+            console.log(" ========= Error or no project found")
+            res.redirect('/account/services')
+          } else if (!project.owner) {
+            console.log(" ========= Project cannot be accessed, since it does not have an owner")
+            res.redirect('/account/services')
+          } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
+            console.log(" ========= Access denied: Not your project")
+            res.redirect('/account/services')
+          } else {
+            let curInformation = new projectInformation(loggedInUser.getGitlabUserId()!, project.name, project.description,
+              req.query.id, project.avatar_url, project.path_with_namespace)
+            
+            res.render(lang+'/account/updateInformation', {
+              user: loggedInUser,
+              information: curInformation
+            })
+          }
+        }
+      }
+    }
+  })
+  // update a website
+  app.post('/updateInformation', async function(req:any, res:any){
+    if( !req.isAuthenticated() ) {
+      res.redirect('/login')
+    } else {
+      let loggedInUser = await getLoggedInUserData(req.user.email)
+
+      if (!loggedInUser) {
+        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 {
+          let projectName = req.body.name.toLowerCase().replace(/\s/g, '-')
+          let projectDesc = req.body.description
+          let updatedInformation = new projectInformation(loggedInUser.getGitlabUserId()!, projectName, projectDesc, req.query.id)
+          let newLogoFile:any
+  
+          async.waterfall([
+            function(callback:any){ // upload logo
+              if(!req.files) {
+                callback(null, newLogoFile)
+              } else {
+                newLogoFile = req.files.logo
+                newLogoFile.mv(logoDir + newLogoFile.name, function(err:any) {
+                  newLogoFile = logoDir + newLogoFile.name
+                  callback(err, newLogoFile)
+                })
+              }
+            },
+            async function(newLogoFile:any){ // update gitlab page
+              let updatedPages = await gitlab.updateProject(updatedInformation, newLogoFile)
+              
+              if (updatedPages.status) {
+                if(updatedPages.data.message.name == "has already been taken") {
+                  res.flash("error", "Der Projektname '"+projectName+"' ist bereits vergeben, bitte wählen Sie einen anderen Namen.")
+                } else {
+                  res.flash("error", "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. ")
+                }
+              } else {
+                updatedInformation.setLogo(updatedPages.avatar_url)
+                updatedInformation.setPath(updatedPages.path)
+                res.flash("success", "Ihre Website wurde aktualisiert")
+              }
+
+              res.redirect('/account/updateInformation?id='+updatedInformation.getId())
+            }
+          ], function (err) {
+            if(err) console.log(err)
+            if(newLogoFile){ // remove logo
+              fs.unlink(newLogoFile, (err) => {
+                if(err) console.log(err)
+              })
+            }
+          })
+        }
+      }
+    }
+  })
+
+  app.delete('/deleteProject', async function(req:any, res:any){
+    if( !req.isAuthenticated() ) {
+      res.redirect('/login')
+    } else {
+      let loggedInUser = await getLoggedInUserData(req.user.email)
+      if (!loggedInUser) {
+        res.redirect('/login')
+      } else {
+        let projectId = req.body.id
+
+        if (projectId) {
+          // check if the owner is valid
+          let project = await gitlab.getProjectById(projectId)
+          if (!project) {
+            console.log(" ========= Error or no project found")
+          } else if (!project.owner) {
+            console.log(" ========= Project cannot be accessed, since it does not have an owner")
+          } else if (project.owner.id != loggedInUser.getGitlabUserId()) {
+            console.log(" ========= Access denied: Not your project")
+          } else {
+            let isDeleted = await gitlab.deleteProjectById(projectId)
+            if (!isDeleted) {
+              res.flash("error", "Project cannot be deleted. Please try again.")
+            }
+          }
+        }
+        res.redirect('/account/services')
+      }
+    }
+  })
+
+}
\ No newline at end of file
diff --git a/routes/public.js b/routes/public.js
deleted file mode 100644
index e6cd132aafd32c7f576bf6c5cf43b368cc232aca..0000000000000000000000000000000000000000
--- a/routes/public.js
+++ /dev/null
@@ -1,296 +0,0 @@
-const methods = require('../functions/methods')
-const async = require('async')
-const mailer = require('../config/mailer')
-const constants = require('../config/const')
-// pwd encryption
-const crypto = require('crypto')
-const bcrypt = require('bcryptjs')
-const saltRounds = 10
-const salt = 64
-
-module.exports = function (app, config, lang) {
-
-    // ================== NEW USERS REGISTRATION ======================
-
-    app.get('/registration', function(req, res) {
-        res.render(lang+'/account/registration')
-    })
-    app.post('/registration', function(req, res) {
-        // user data
-        var curDate = new Date()
-        var 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,
-          createdDate: curDate.toISOString().slice(0,10)
-        }
-    
-        var userEmail = userData.email
-        var pos = userEmail.indexOf('@')
-        var emailLength = userEmail.length
-        var emailDomain = userEmail.slice(pos, emailLength);
-    
-        if ( emailDomain.toLowerCase() == "@hft-stuttgart.de") {
-            res.flash('error', "Fehlgeschlagen: HFT-Account")
-            res.redirect('/account/registration')
-        } else {
-          let token
-          async.waterfall([
-            function(done) {
-              crypto.randomBytes(20, function(err, buf) {
-                token = buf.toString('hex');
-                done(err, token);
-              });
-            },
-            // encrypt password
-            function(token, done) {
-              bcrypt.genSalt(saltRounds, function(err, salt) {
-                bcrypt.hash(req.body.inputPassword, salt, function(err, hash) {
-                  var newAccount = {
-                    profile: userData,
-                    password: hash,
-                    verificationToken: token
-                  }
-                  done(err, newAccount)
-                });
-              });
-            },
-            // save data
-            function(newAccount, err) {
-              methods.registerNewUser(newAccount, function(err){
-                if (err) {
-                  res.flash('error', "Fehlgeschlagen")
-                }
-                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 <a href='+config.app.host+'/verifyAccount?token='+token+'>diesen Link</a> ' +
-                    '<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 = req.body.inputEmail;
-                  mailer.options.subject = emailSubject;
-                  mailer.options.html = emailContent;
-                  mailer.transport.sendMail(mailer.options, function(err) {
-                    if (err) {
-                      console.error('cannot send email')
-                      throw err
-                    }
-                  })
-                  // user feedback
-                  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'+
-                    'Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner.')
-                }
-                res.redirect('/account/registration')
-              })
-            }
-          ])
-        }
-    })
-
-    // =================== USERS VERIFICATION =========================
-
-    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 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
-                })
-            }
-          }
-        })        
-      }
-    })
-
-    // ==================== FORGOT PASSWORD ===========================
-
-    app.get('/forgotPwd', function (req, res) {
-      res.render(lang+'/account/forgotPwd', {
-        user: req.user
-      })
-    })
-    app.post('/forgotPwd', function(req, res) {
-      let emailAddress = req.body.inputEmail
-      async.waterfall([
-        function(done) {
-          crypto.randomBytes(20, function(err, buf) {
-            var token = buf.toString('hex')
-            done(err, token)
-          })
-        },
-        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) {
-              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) {
-          res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.')
-        }
-        else {
-          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', 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', async function(req, res) {
-      var newPwd = req.body.inputNewPwd
-
-      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')
-              }
-            })
-          });
-        });
-      }
-
-    })
-
-    // ======================= CONTACT FORM ===========================
-
-    app.get('/contact', function (req, res) {
-      res.render(lang+'/account/contact', {
-        user: req.user
-      })
-    })
-    app.post('/contact', function(req, res, next) {
-        //methods.currentDate();
-        let emailAddress = req.body.inputEmail;
-        let supportAddress = "support-transfer@hft-stuttgart.de";
-        let inputName = req.body.name;
-        let inputContent = req.body.message;
-        let emailContent = "Es wurde eine Anfrage an das Transferportal gestellt: \n\n NAME: " + inputName + "\n NACHRICHT:\n "+ inputContent;
-        let emailSubject = "Ihre Anfrage an das Transferportal";
-        async.waterfall([
-          function(done) {
-              // send email
-              mailer.options.to = supportAddress;
-              mailer.options.cc = emailAddress;
-              mailer.options.subject = emailSubject;
-              mailer.options.text = emailContent;
-              mailer.transport.sendMail(mailer.options, function(err) {
-                done(err, 'done');
-              });
-            }
-        ], function(err) {
-          if (err) {
-            console.error(err)
-            res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
-          }
-          else {
-            res.flash('success', 'Vielen Dank für Ihre Anfrage. Wir melden uns baldmöglichst bei Ihnen. Eine Kopie Ihrer Anfrage wurde an ' + emailAddress + ' versandt.');
-          }
-          res.redirect('/account/contact')
-        })
-    })
-
-}
\ No newline at end of file
diff --git a/routes/public.ts b/routes/public.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a5c7bd132bd78b93e6f0c70777e69a80cc1c08d7
--- /dev/null
+++ b/routes/public.ts
@@ -0,0 +1,292 @@
+import async from 'async'
+import bcrypt from 'bcryptjs'
+import methods from '../functions/methods'
+import mailer from '../config/mailer'
+import constants from '../config/const'
+
+const saltRounds:number = 10
+const salt:number = 64
+
+export = function (app:any, config:any, lang:string) {
+
+  // ================== NEW USERS REGISTRATION ======================
+  app.get('/registration', function(req:any, res:any) {
+    res.render(lang+'/account/registration')
+  })
+  app.post('/registration', function(req:any, res:any) {
+    // user data
+    var curDate:Date = new Date()
+    var userData:any = {
+      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,
+      createdDate: curDate.toISOString().slice(0,10)
+    }
+    
+    var userEmail:any = userData.email
+    var pos:number = userEmail.indexOf('@')
+    var emailLength:number = userEmail.length
+    var emailDomain:any = userEmail.slice(pos, emailLength);
+    
+    if ( emailDomain.toLowerCase() == "@hft-stuttgart.de") {
+      res.flash('error', "Fehlgeschlagen: HFT-Account")
+      res.redirect('/account/registration')
+    } else {
+      async.waterfall([
+        function(done:any) {
+          // generate token
+          let token:string = '';
+          let randomChars:string = 'abcdefghijklmnopqrstuvwxyz0123456789';
+          for ( let i = 0; i<40; i++ ) {
+            token += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
+          }
+          // encrypt password
+          bcrypt.genSalt(saltRounds, function(err, salt) {
+            bcrypt.hash(req.body.inputPassword, salt, function(err:any, hash:any) {
+              var newAccount:any = {
+                profile: userData,
+                password: hash,
+                verificationToken: token
+              }
+              done(err, newAccount)
+            });
+          });
+        },
+        // save data
+        function(newAccount:any, err:any) {
+          methods.registerNewUser(newAccount, function(err:any){
+            if (err) {
+              res.flash('error', "Fehlgeschlagen")
+            }
+            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 <a href='+config.app.host+'/verifyAccount?token='+newAccount.verificationToken+'>diesen Link</a> ' +
+                '<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 = req.body.inputEmail;
+              mailer.options.subject = emailSubject;
+              mailer.options.html = emailContent;
+              mailer.transporter.sendMail(mailer.options, function(err:any) {
+                if (err) {
+                  console.error('Cannot send email. [Error] '+err)
+                  throw err
+                }
+              })
+              // user feedback
+              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'+
+                'Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner.')
+              }
+              res.redirect('/account/registration')
+            })
+        }
+      ])
+    }
+  })
+
+  // =================== USERS VERIFICATION =========================
+
+  app.get("/verifyAccount", async function(req:any, res:any){
+    let userId:number = 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:any = {
+        id: userId,
+        verificationStatus: 1
+      }
+      methods.verifyUserAccount(userData, async function(err:any){
+        if (err) {
+          console.log("Error: "+err)
+          res.render(lang+'/account/verification', {
+            status: false
+          });
+        } else {
+          // send welcome email after successful account verification
+          let userEmail:string = await methods.getUserEmailById(userId)
+          if (!userEmail) {
+            res.render(lang+'/account/verification', {
+              status: false
+            })
+          } 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.transporter.sendMail(mailer.options, function(err:any) {
+                if (err) {
+                  console.log('cannot send email')
+                  throw err
+                }
+              })
+  
+              res.render(lang+'/account/verification', {
+                status: true
+              })
+          }
+        }
+      })        
+    }
+  })
+
+  // ==================== FORGOT PASSWORD ===========================
+
+  app.get('/forgotPwd', function (req:any, res:any) {
+    res.render(lang+'/account/forgotPwd', {
+      user: req.user
+    })
+  })
+  app.post('/forgotPwd', function(req:any, res:any) {
+    let emailAddress = req.body.inputEmail
+    async.waterfall([
+      async function(done:any) {
+        let user = await methods.checkUserEmail(emailAddress)
+        if (!user) {
+          console.log('No user found: '+emailAddress)
+        } else {
+          // generate token
+          let token:string = '';
+          let randomChars:string = 'abcdefghijklmnopqrstuvwxyz0123456789';
+          for ( let i = 0; i<40; i++ ) {
+            token += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
+          }
+
+          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
+          }
+          let result = await methods.updateCredential(credentialData)
+          if (!result) {
+            console.log('failed to update credential')
+          } else {
+            // send email
+            mailer.options.to = emailAddress
+            mailer.options.subject = emailSubject
+            mailer.options.html = emailContent
+            mailer.transporter.sendMail(mailer.options, function(err:any) {
+              if (err) { console.error(err) }
+            })
+          }
+        }
+        done(null)
+      }
+    ], function(err:any) {
+      if (err) {
+        res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.')
+      }
+      else {
+        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', async function(req:any, res:any) {
+      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', async function(req:any, res:any) {
+      var newPwd = req.body.inputNewPwd
+
+      var 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, async function(err:any, hash) {
+            var credentialData = {
+              password: hash,
+              user_id: user.user_id
+            }
+            // update password
+            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 = 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')
+          });
+        });
+      }
+
+  })
+
+  // ======================= CONTACT FORM ===========================
+  app.get('/contact', function (req:any, res:any) {
+      res.render(lang+'/account/contact', {
+        user: req.user
+      })
+  })
+  app.post('/contact', function(req:any, res:any, next:any) {
+        //methods.currentDate();
+        let emailAddress = req.body.inputEmail;
+        let supportAddress = "support-transfer@hft-stuttgart.de";
+        let inputName = req.body.name;
+        let inputContent = req.body.message;
+        let emailContent = "Es wurde eine Anfrage an das Transferportal gestellt: \n\n NAME: " + inputName + "\n NACHRICHT:\n "+ inputContent;
+        let emailSubject = "Ihre Anfrage an das Transferportal";
+        async.waterfall([
+          function(done:any) {
+            // send email
+            mailer.options.to = supportAddress;
+            mailer.options.cc = emailAddress;
+            mailer.options.subject = emailSubject;
+            mailer.options.text = emailContent;
+            mailer.transporter.sendMail(mailer.options, function(err:any) {
+              done(err, 'done');
+            });
+          }
+        ], function(err:any) {
+          if (err) {
+            console.error(err)
+            res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
+          }
+          else {
+            res.flash('success', 'Vielen Dank für Ihre Anfrage. Wir melden uns baldmöglichst bei Ihnen. Eine Kopie Ihrer Anfrage wurde an ' + emailAddress + ' versandt.');
+          }
+          res.redirect('/account/contact')
+        })
+  })
+ 
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..1519fee76e91ea94764d0ac22eec6f766f63686e
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,11 @@
+{
+  "compilerOptions": {
+    "target": "es6",
+    "module": "commonjs",
+    "rootDir": "./",
+    "outDir": "./built",
+    "esModuleInterop": true,
+    "strict": true,
+    "allowJs": true
+  }
+}
\ No newline at end of file