Commit 58fc4884 authored by Wolfgang Knopki's avatar Wolfgang Knopki
Browse files

Merge branch 'prepare_prod' into 'master'

Prepare prod

See merge request !91
1 merge request!91Prepare prod
Pipeline #4342 passed with stage
in 15 seconds
Showing with 1283 additions and 889 deletions
+1283 -889
...@@ -17,10 +17,11 @@ ...@@ -17,10 +17,11 @@
}, },
"scripts": { "scripts": {
"start": "nodemon app.js", "start": "nodemon app.js",
"test": "" "test": "jest"
}, },
"dependencies": { "dependencies": {
"async": "^3.1.0", "async": "^3.1.0",
"axios": "^0.21.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"compression": "^1.7.4", "compression": "^1.7.4",
...@@ -29,20 +30,25 @@ ...@@ -29,20 +30,25 @@
"errorhandler": "1.4.3", "errorhandler": "1.4.3",
"express": "^4.17.1", "express": "^4.17.1",
"express-fileupload": "^1.1.6", "express-fileupload": "^1.1.6",
"express-flash": "0.0.2", "express-flash-2": "^1.0.1",
"express-session": "^1.17.0", "express-session": "^1.17.0",
"form-data": "^3.0.0",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"helmet": "^3.23.3", "helmet": "^3.23.3",
"i18n": "^0.8.5", "i18n": "^0.8.5",
"jest": "^26.6.3",
"method-override": "^3.0.0",
"morgan": "^1.9.1", "morgan": "^1.9.1",
"mysql": "^2.17.1", "mysql": "^2.17.1",
"mysql2": "^2.2.5",
"nodemailer": "^6.3.1", "nodemailer": "^6.3.1",
"nodemon": "^2.0.1",
"passport": "0.3.2", "passport": "0.3.2",
"passport-saml": "^1.2.0", "passport-saml": "^2.1.0",
"pug": "^2.0.4" "pug": "^3.0.2"
},
"devDependencies": {
"nodemon": "^2.0.1"
}, },
"devDependencies": {},
"engines": { "engines": {
"node": ">= 4.0.0" "node": ">= 4.0.0"
}, },
......
public/default/logo.png

84.7 KB

...@@ -70,8 +70,8 @@ function head(){ ...@@ -70,8 +70,8 @@ function head(){
alertbutton.innerHTML = "×"; alertbutton.innerHTML = "×";
alertdiv.innerHTML="<strong>Disclaimer</strong> This website is under construction and in prototype-phase. It is not for public use." alertdiv.innerHTML="<strong>Disclaimer</strong> This website is under construction and in prototype-phase. It is not for public use."
prependChild(alertdiv, alertbutton); prependChild(alertdiv, alertbutton);
alertdiv.classList.add('alert','alert-danger', 'alert-dismissible', 'fade','show'); alertdiv.classList.add('alert','alert-danger', 'alert-dismissible', 'fade','show', 'text-center');
alertdiv.style = "text-align:center;"; //alertdiv.style = "text-align:center;";
navheader.appendChild(alertdiv); navheader.appendChild(alertdiv);
let navbar = document.createElement('nav'); let navbar = document.createElement('nav');
navbar.classList.add("navbar", "navbar-default"); navbar.classList.add("navbar", "navbar-default");
......
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
// ==== USER ACOOUNT API ====
var dbconn = require('./dbconn')
module.exports = function (app) {
//console.log(dbconn);
//var con = dbconn.connection
app.get('/api/v1/profile', function (req, res) {
if (req.isAuthenticated()) {
// read data based on email
dbconn.user.query('SELECT * FROM user WHERE email="'+req.user.email+'"', function (err, rows, fields) {
if (err) throw err
res.send(rows[0])
})
} else {
res.send('authentication required');
}
});
}
\ No newline at end of file
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
const fs = require('fs')
const SamlStrategy = require('passport-saml').Strategy
const dbconn = require('./dbconn')
const methods = require('./methods')
// 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('./mailer')
module.exports = function (app, config, passport, i18n) {
// =========== PASSPORT =======
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
const mailSignature = 'Mit den besten Grüßen,<br/>das Transferportal-Team der HFT Stuttgart<br/><br/>' +
'Transferportal der Hochschule für Technik Stuttgart<br/>' +
'Schellingstr. 24 70174 Stuttgart<br/>' +
'm4lab@hft-stuttgart.de<br/>' +
'<a href="https://transfer.hft-stuttgart.de">https://transfer.hft-stuttgart.de</a><br/>' +
'<a href="http://www.hft-stuttgart.de/Aktuell/"><img border="0" alt="HFT" src="https://m4lab.hft-stuttgart.de/img/signature/hft_logo.png" width="30" height="30"></a> &nbsp;' +
'<a href="http://www.facebook.com/hftstuttgart"><img border="0" alt="Facebook" src="https://m4lab.hft-stuttgart.de/img/signature/fb_bw.png" width="30" height="30"></a> &nbsp;' +
'<a href="https://www.instagram.com/hft_stuttgart/"><img border="0" alt="Instagram" src="https://m4lab.hft-stuttgart.de/img/signature/instagram_bw.png" width="30" height="30"></a> &nbsp;' +
'<a href="https://twitter.com/hft_presse"><img border="0" alt="Twitter" src="https://m4lab.hft-stuttgart.de/img/signature/twitter_bw.png" width="30" height="30"></a> &nbsp;' +
'<a href="https://www.youtube.com/channel/UCi0_JfF2qMZbOhOnNH5PyHA"><img border="0" alt="Youtube" src="https://m4lab.hft-stuttgart.de/img/signature/youtube_bw.png" width="30" height="30"></a> &nbsp;' +
'<a href="http://www.hft-stuttgart.de/Aktuell/Presse-Marketing/SocialMedia/Snapcode HFT_Stuttgart.jpg/photo_view">' +
'<img border="0" alt="Snapchat" src="https://m4lab.hft-stuttgart.de/img/signature/snapchat_bw.png" width="30" height="30"></a>' +
'<br/><img border="0" src="https://m4lab.hft-stuttgart.de/img/signature/inno_bw.png" width="150" height="100">'
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);
}
);
// ================ test i18n ==================
i18n.setLocale('de');
app.get('/de', function(req, res) {
var greeting = i18n.__('Hello World')
res.send(greeting)
});
var lang = 'DE'
// ======== APP ROUTES - ACCOUNT ====================
var updatePasswordMailSubject = "Ihr Passwort für das Transferportal wurde gespeichert."
// var mailSignature = "Mit den besten Grüßen,\ndas Transferportal-Team der HFT Stuttgart\n\n"+
// "Transferportal der Hochschule für Technik Stuttgart\n"+
// "Schellingstr. 24\n"+
// "70174 Stuttgart\n"+
// "m4lab@hft-stuttgart.de\n"+
// "https://transfer.hft-stuttgart.de"
var updatePasswordMailContent = '<div>Lieber Nutzer,<br/><br/>Ihr Passwort wurde erfolgreich geändert.<br/><br/>' + mailSignature + '</div>';
app.get('/', function (req, res) {
if (req.isAuthenticated()) {
methods.getUserByEmail(req.user.email, function(data, err){
if (!err) {
res.render(lang+'/account/home', {
user: data
});
}
})
} else {
res.redirect('/login'); // localhost
}
});
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', function (req, res) {
if (req.isAuthenticated()) {
methods.getUserByEmail(req.user.email, function(data, err){
if (!err) {
if (data.verificationStatus == 1) {
console.log(data)
res.render(lang+'/account/profile', {
user: data,
email: req.user.email
})
}
else {
res.render(lang+'/account/home', {
user: data
});
}
}
})
} else {
res.redirect('/login');
}
});
app.get('/services', function (req, res) {
if (req.isAuthenticated()) {
methods.getUserByEmail(req.user.email, function(data, err){
if (!err) {
if (data.verificationStatus == 1) {
res.render(lang+'/account/services', {
user: data
});
/* !!! DO NOT DELETE. TEMPORARILY DISABLED FOR FUTURE USE. !!!
async.waterfall([
// get userId by email from userdb
function(done) {
methods.getUserIdByEmail(req.user.email, function(userId, err) {
if (!err) {
done(err, userId)
}
})
},
// get user-project-role from userdb
function(userId, done) {
methods.getUserProjectRole(userId, function(userProjects, err) {
if (!err) {
done(err, userProjects)
}
})
},
// get all projects from projectdb
function(userProjects, done) {
methods.getAllProjects(function(projectsOverview, err) {
if (!err) {
done(err, userProjects, projectsOverview)
}
})
},
// create JSON object of projects and user status for front-end
function(userProjects, projectsOverview, done) {
var allProjects = [] // JSON object
var userProjectId = [] // array of user's project_id
for (var i = 0; i < userProjects.length; i++) {
userProjectId.push(userProjects[i].project_id)
}
for (var i = 0; i < projectsOverview.length; i++) {
// check if projectId is exist in userProjectId[]
var status = false
if (userProjectId.indexOf(projectsOverview[i].id) > -1) {
status = true
}
// add data to JSON object
allProjects.push({
id: projectsOverview[i].id,
title: projectsOverview[i].title,
summary: projectsOverview[i].onelinesummary,
cp: projectsOverview[i].contact_email,
userStatus: status
});
}
// render the page
res.render(lang+'/account/services', {
user: data,
project: allProjects
});
}
])
*/
}
else {
res.render(lang+'/account/home', {
user: data
});
}
}
})
} else {
res.redirect('/login');
}
});
app.get('/security', function (req, res) {
if (req.isAuthenticated()) {
methods.getUserByEmail(req.user.email, function(data, err){
if (!err) {
if (data.verificationStatus == 1 && data.m4lab_idp == 1) {
res.render(lang+'/account/security', {
user: data
})
}
else {
res.render(lang+'/account/home', {
user: data
});
}
}
})
} else {
res.redirect('/login');
}
});
app.post('/updateProfile', 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()) {
if (userData.email) {
dbconn.user.query('UPDATE user SET ? WHERE email = "' +userData.email+'"', userData, function (err, rows, fields) {
//if (err) throw err;
if (err) {
req.flash('error', "Failed");
}
else {
//req.flash('success', 'Profile updated!');
req.flash('success', 'Ihr Benutzerprofil wurde aktualisiert!');
}
res.redirect('/account/profile');
})
}
} else {
res.redirect('/login');
}
});
app.post('/changePwd', function (req, res) {
if (req.isAuthenticated()) {
var currPwd = req.body.inputCurrPwd
var newPwd = req.body.inputNewPwd
var retypePwd = req.body.inputConfirm
methods.getUserIdByEmail(req.user.email, function(userId, err) {
if (!err) {
// Load hashed passwd from DB
dbconn.user.query('SELECT password FROM credential WHERE user_id='+userId, 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) {
//req.flash('error', "Sorry, your password was incorrect. Please double-check your password.")
req.flash('error', "Das Passwort ist leider falsch. Bitte überprüfen Sie Ihre Eingabe.")
//res.redirect('/security')
res.redirect('/account/security')
}
else {
if ( newPwd != retypePwd ) {
//req.flash('error', "Passwords do no match. Please make sure you re-type your new password correctly.")
req.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) {
//req.flash('error', "Database error: Password cannot be modified.")
req.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.")
throw err
}
else {
//req.flash('success', "Pasword updated!")
req.flash('success', "Passwort aktualisiert!")
mailer.options.to = req.user.email
//mailOptions.subject = "Your M4_LAB Password has been updated."
mailer.options.subject = updatePasswordMailSubject
mailer.options.html = updatePasswordMailContent
mailer.transport.sendMail(mailer.options, function(err) {
if (err) {
console.log(err)
}
});
}
res.redirect('/account/security')
})
});
});
}
}
})
})
}
})
}
else {
res.redirect('/login');
}
});
app.get('/forgotPwd', function (req, res) {
res.render(lang+'/account/forgotPwd', {
user: req.user
});
});
app.post('/forgotPwd', function(req, res, next) {
//methods.currentDate();
var emailAddress = req.body.inputEmail;
/* var emailContent = "Hi there,\n\n"+
"we've received a request to reset your password. However, this email address is not on our database of registered users.\n\n"+
"Thanks,\nM4_LAB Team";
var emailSubject = "Account Access Attempted"; */
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
methods.checkUserEmail(emailAddress, function(err, user){
if (user) {
console.log("email: user found");
//var emailSubject = "M4_LAB Password Reset";
var emailSubject = "Ihre Passwort-Anfrage an das Transferportal der HFT Stuttgart";
/* var emailContent = "Hi User,\n\n"+
"we've received a request to reset your password. If you didn't make the request, just ignore this email.\n\n"+
"Otherwise, you can reset your password using this link: http://m4lab.hft-stuttgart.de/account/reset/" + token + "\n" +
"This password reset is only valid for 1 hour.\n\n"+
"Thanks,\nM4_LAB Team" */
// var emailContent = "Lieber Nutzer,\n\n"+
// "wir haben Ihre Anfrage zur Erneuerung Ihres Passwortes erhalten. Falls Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese E-Mail.\n\n"+
// "Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: http://m4lab.hft-stuttgart.de/account/reset/" + token + "\n" + // test server
// //"Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: http://localhost:9989/reset/" + token + "\n" + // localhost
// "Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.\n\n"+mailSignature
var emailContent = '<div>Lieber Nutzer, Varun<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: http://m4lab.hft-stuttgart.de/account/reset/' + token + '<br/>' + // test server
'Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.<br/></p>' + mailSignature + '</div>';
var credentialData = {
user_id: user.id,
resetPasswordToken: token,
resetPasswordExpires: Date.now() + 3600000 // 1 hour
}
methods.updateCredential(credentialData, function(err) {
done(err, token, user);
});
// send email
mailer.options.to = emailAddress;
mailer.options.subject = emailSubject;
mailer.options.html = emailContent;
mailer.transport.sendMail(mailer.options, function(err) {
done(err, 'done');
});
}
else {
//done(err, null, null);
done(err, 'no user found');
}
});
}
], function(err) {
if (err) {
//req.flash('error', 'An error occured. Please try again.');
req.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
else {
//req.flash('success', 'If your email is registered, an e-mail has been sent to ' + emailAddress + ' with further instructions.');
req.flash('success', 'Wenn Ihre E-Mail-Adresse registriert ist, wurde eine E-Mail mit dem weiteren Vorgehen an ' + emailAddress + ' versendet.');
}
//res.redirect('/forgotPwd'); // deployment
res.redirect('/account/forgotPwd'); // localhost
});
});
app.get('/reset/:token', function(req, res) {
methods.getUserByToken(req.params.token, function(err, user){
if (!user) {
//req.flash('error', 'Password reset token is invalid or has expired.');
req.flash('error', 'Der Schlüssel zum zurücksetzen des Passworts ist ungültig oder abgelaufen.');
//res.redirect('/forgotPwd'); // deployment
res.redirect('/account/forgotPwd'); // deployment
}
else {
res.render(lang+'/account/reset');
}
});
});
app.post('/reset/:token', function(req, res) {
var newPwd = req.body.inputNewPwd
methods.getUserByToken(req.params.token, function(err, user){
if (user) {
// encrypt password
bcrypt.genSalt(saltRounds, function(err, salt) {
bcrypt.hash(newPwd, salt, function(err, hash) {
var credentialData = {
password: hash,
user_id: user.user_id
}
// update password
methods.updateCredential(credentialData, function(err){
if (err) {
//req.flash('error', "Database error: Password cannot be modified.")
req.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.")
throw err
}
else {
//req.flash('success', "Your pasword has been updated.")
req.flash('success', "Passwort aktualisiert!")
// send notifiaction email
mailer.options.to = user.email
mailer.options.subject = updatePasswordMailSubject
mailer.options.html = updatePasswordMailContent
mailer.transport.sendMail(mailer.options, function(err) {
if (err) {
console.log(err)
}
});
// redirect to login page
res.redirect('/login')
}
})
});
});
}
else {
req.flash('error', "User not found.")
res.redirect('/login')
}
});
});
// ============= 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") {
req.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) {
req.flash('error', "Fehlgeschlagen")
}
else {
// send email
var emailSubject = "Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto"
// var emailContent = "Lieber Nutzer,\n\n"+
// "vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart.\n"+
// "Um Ihre Anmeldung zu bestätigen, klicken Sie bitte diesen Link: "+config.app.host+"/verifyAccount?token="+token+"\n"+
// "Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.\n\n"+
// "Sollten Sie sich selbst nicht mit Ihren Daten am Transferportal registriert haben, ignorieren Sie diese E-Mail bitte.\n\n"+mailSignature
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/>' + 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.log('cannot send email')
throw err
}
})
// user feedback
req.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')
})
}
])
}
})
// ============= USER VERIFICATION ================================
app.get("/verifyAccount", function(req, res){
console.log(req.query)
methods.getUserIdByVerificationToken(req.query.token, function(userId, err){
if (userId) {
let userData = {
id: userId,
verificationStatus: 1
}
methods.verifyUserAccount(userData, function(err){
if (err) {
console.log("Error: "+err)
res.render(lang+'/account/verification', {
status: false
});
}
else {
// send welcome email after successful account verification
methods.getUserById(userId, function(data, err){
if (err) {
console.log("Error: "+err)
}
else {
// send email
var emailSubject = "Herzlich willkommen"
// var emailContent = "Lieber Nutzer,\n\n"+
// "herzlich willkommen beim Transferportal der HFT Stuttgart!\n"+
// "Sie können nun alle Dienste des Portals nutzen.\n\n"+mailSignature
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/>' + mailSignature;
mailer.options.to = data.email;
mailer.options.subject = emailSubject;
mailer.options.html = emailContent;
mailer.transport.sendMail(mailer.options, function(err) {
if (err) {
console.log('cannot send email')
throw err
}
})
}
})
res.render(lang+'/account/verification', {
status: true
});
}
})
}
else {
res.render(lang+'/account/verification', {
status: null
});
}
})
})
app.get("/resendVerificationEmail", function(req, res){
if (req.isAuthenticated()) {
var emailAddress = req.user.email
methods.getUserIdByEmail(req.user.email, function(userId, err) {
if (!err) {
// get token
methods.getVerificationTokenByUserId(userId, function(token, err){
if (!err) {
if (token) {
// send email
var emailSubject = "Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto"
// var emailContent = "Lieber Nutzer,\n\n"+
// "vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart. "+
// "\nUm Ihre Anmeldung zu bestätigen, klicken Sie bitte diesen Link: "+config.app.host+"/verifyAccount?token="+token+
// "\n\nOhne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.\n\n"+mailSignature
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/>' + mailSignature +
'</div>';
mailer.options.to = emailAddress;
mailer.options.subject = emailSubject;
mailer.options.html = emailContent;
mailer.transport.sendMail(mailer.options, function(err) {
if (err) {
console.log('cannot send email')
throw err
}
})
res.send(true)
}
else {
res.send(false)
}
}
else {
console.log(err)
}
})
}
})
}
})
app.get('/email/:email', function(req, res) {
methods.checkUserEmail(req.params.email, function(err, user){
if (!err) {
if (user) {
res.send(false)
}
else {
res.send(true)
}
}
})
})
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) {
req.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
else {
req.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('/forgotPwd'); // deployment
res.redirect('/account/contact'); // localhost
});
});
};
\ No newline at end of file
...@@ -6,24 +6,19 @@ html(lang="de") ...@@ -6,24 +6,19 @@ html(lang="de")
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no") meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no")
link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css") link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css")
link(rel="stylesheet", type="text/css", href="/css/m4lab.css") link(rel="stylesheet", type="text/css", href="/css/m4lab.css")
link(rel="stylesheet", type="text/css", href="/fonts/ionicons.min.css")
link(rel="stylesheet", type="text/css", href="/css/Contact-Form-Clean.css") link(rel="stylesheet", type="text/css", href="/css/Contact-Form-Clean.css")
link(rel="stylesheet", type="text/css", href="/css/Testimonials.css")
link(rel="stylesheet", type="text/css", href="/css/custom/login.css")
link(rel="stylesheet", href="https://use.fontawesome.com/releases/v5.8.2/css/all.css", integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay", crossorigin="anonymous") link(rel="stylesheet", href="https://use.fontawesome.com/releases/v5.8.2/css/all.css", integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay", crossorigin="anonymous")
body body
div(class="container") div(class="container")
div(class="row") div(class="row")
div(class="col-md-12" style="margin-bottom: 40px;") div(class="col-md-12 margin_bottom_40")
img(class="mx-auto" src="/img/Kontakt.jpg" width="100%") img(class="mx-auto" src="/img/Kontakt.jpg" width="100%")
div(class="contact-clean" style="background-color: rgb(234,234,234);") div(class="contact-clean background_eaeaea")
if successes if flash.success
for success in successes div.alert.alert-success.alert-dismissible #{flash.success}
div.alert.alert-success.alert-dismissible #{ success }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if errors if flash.error
for error, i in errors div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
div.alert.alert-danger.alert-dismissible.fade.show #{ error }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
form(method="POST") form(method="POST")
h2(class="text_center") Kontaktieren Sie uns h2(class="text_center") Kontaktieren Sie uns
...@@ -34,18 +29,18 @@ html(lang="de") ...@@ -34,18 +29,18 @@ html(lang="de")
div(class="form-group") div(class="form-group")
textarea#message(class="form-control" name="message" placeholder="Nachricht" rows="14") textarea#message(class="form-control" name="message" placeholder="Nachricht" rows="14")
div(class="form-group") div(class="form-group")
input#submitBtn(class="btn btn-primary" type="submit" style="background-color: #8a348b;" value="SENDEN") input#submitBtn(class="btn btn-primary" type="submit" value="SENDEN")
div(class="contact-clean" style="background-color: rgb(234,234,234);padding: 80px;padding-top: 0px;") div(class="contact-clean contact_footer")
form(method="POST") form
p(style="margin-top: 25px;") <strong>Hochschule für Technik Stuttgart</strong><br/>Institut für Angewandte Forschung<br/>Innovative Hochschule - Projekt M4_LAB<br/>Schellingstr. 24<br/>70174 Stuttgart<br/>Deutschland<br/><br/><a href="mailto:support-transfer@hft-stuttgart.de">support-transfer@hft-stuttgart.de</a><br/><br/><a href="https://www.hft-stuttgart.de/">www.hft-stuttgart.de</a> / <a href="https://www.hft-stuttgart.de/M4LAB">www.hft-stuttgart.de/M4LAB</a><br/> p(class="m_top_25") <strong>Hochschule für Technik Stuttgart</strong><br/>Institut für Angewandte Forschung<br/>Innovative Hochschule - Projekt M4_LAB<br/>Schellingstr. 24<br/>70174 Stuttgart<br/>Deutschland<br/><br/><a href="mailto:support-transfer@hft-stuttgart.de">support-transfer@hft-stuttgart.de</a><br/><br/><a href="https://www.hft-stuttgart.de/">www.hft-stuttgart.de</a> / <a href="https://www.hft-stuttgart.de/M4LAB">www.hft-stuttgart.de/M4LAB</a><br/>
div(style="background-color: rgba(138,52,139,0.45);") div(class="background_8a348b")
div(class="container") div(class="container")
div(class="row") div(class="row")
div(class="col-md-4 col-lg-2") div(class="col-md-4 col-lg-2")
div(class="col-md-4 col-lg-8") div(class="col-md-4 col-lg-8")
div(style="background-color: #feffff;margin: 0px;padding: 60px;padding-top: 20px;padding-bottom: 20px;") div(class="contact_foot_message")
img(class="d-flex d-lg-flex justify-content-center justify-content-lg-center align-items-lg-start mx-auto" src="/img/Logo_TV1.png" width="100px" style="padding-bottom: 35px;") img(class="d-flex d-lg-flex justify-content-center justify-content-lg-center align-items-lg-start mx-auto p_bottom_35" src="/img/Logo_TV1.png" width="100px")
h2(class="text-center" style="color: #8a348b;") <strong>Transferportal</strong> h2(class="text-center color_8a348b") <strong>Transferportal</strong>
p(class="text-center") Das Transferportal entsteht in einem Teilprojekt der Innovativen <a href="https://www.hft-stuttgart.de">Hochschule für Technik Stuttgart</a>. Im <a href="https://www.hft-stuttgart.de/forschung/innovative-hochschule-m4-lab">Innovationslabor M4_LAB</a> wird das Transferportal als eine Webpräsenz entwickelt, welches Wissen, Lösungen und Dienste für HFT-Mitglieder, externe Partner und die allgemeine Öffentlichkeit bereitstellt.<br/><br/>Es ergänzt die Informationen der allgemeinen HFT-Webseite durch konkrete Ergebnisse aus Forschung und Entwicklung, verfügbar in verschiedenster Form wie beispielsweise Daten, Dokumentationen und Software-Code.<br/><br/>Zudem stellt es Kollaborationsmittel für Projektpartner und später auch Partizipationsmöglichkeiten für die breite Öffentlichkeit bereit. p(class="text-center") Das Transferportal entsteht in einem Teilprojekt der Innovativen <a href="https://www.hft-stuttgart.de">Hochschule für Technik Stuttgart</a>. Im <a href="https://www.hft-stuttgart.de/forschung/innovative-hochschule-m4-lab">Innovationslabor M4_LAB</a> wird das Transferportal als eine Webpräsenz entwickelt, welches Wissen, Lösungen und Dienste für HFT-Mitglieder, externe Partner und die allgemeine Öffentlichkeit bereitstellt.<br/><br/>Es ergänzt die Informationen der allgemeinen HFT-Webseite durch konkrete Ergebnisse aus Forschung und Entwicklung, verfügbar in verschiedenster Form wie beispielsweise Daten, Dokumentationen und Software-Code.<br/><br/>Zudem stellt es Kollaborationsmittel für Projektpartner und später auch Partizipationsmöglichkeiten für die breite Öffentlichkeit bereit.
div(class="col-md-4 col-lg-2") div(class="col-md-4 col-lg-2")
......
...@@ -12,13 +12,11 @@ html(lang="de") ...@@ -12,13 +12,11 @@ html(lang="de")
div(class="container-fluid") div(class="container-fluid")
div(class="row") div(class="row")
div(class="col-md-6 offset-md-3") div(class="col-md-6 offset-md-3")
if successes if flash.success
for success in successes div.alert.alert-success.alert-dismissible #{flash.success}
div.alert.alert-success.alert-dismissible #{ success }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if errors if flash.error
for error, i in errors div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
div.alert.alert-danger.alert-dismissible.fade.show #{ error }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
form#forgotForm(class="form-signin", method="POST") form#forgotForm(class="form-signin", method="POST")
img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192") img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
......
...@@ -16,7 +16,7 @@ html(lang="de") ...@@ -16,7 +16,7 @@ html(lang="de")
| Wir haben Ihnen eine E-Mail an Ihre verwendete Adresse gesendet. Diese enthält einen Link zur Bestätigung Ihres Accounts. | Wir haben Ihnen eine E-Mail an Ihre verwendete Adresse gesendet. Diese enthält einen Link zur Bestätigung Ihres Accounts.
| Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner. | Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner.
| <br >Falls Sie keine E-Mail von uns erhalten haben, können Sie <a href="javascript:void(0);" onclick="verify();">diese hier</a> erneut anfordern. | <br >Falls Sie keine E-Mail von uns erhalten haben, können Sie <a href="javascript:void(0);" onclick="verify();">diese hier</a> erneut anfordern.
div(class="spinner-border text-secondary", role="status", style="display: none") div(class="spinner-border text-secondary display_none", role="status")
else else
div(class="row min-vh-100 flex-column flex-md-row") div(class="row min-vh-100 flex-column flex-md-row")
aside(class="col-12 col-md-3 p-0 flex-shrink-1") aside(class="col-12 col-md-3 p-0 flex-shrink-1")
...@@ -25,12 +25,12 @@ html(lang="de") ...@@ -25,12 +25,12 @@ html(lang="de")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between") ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="#") a(class="nav-link pl-0 text-nowrap" href="#")
span(class="font-weight-bold" style="color:black;") #{user.firstname} #{user.lastname} span(class="font-weight-bold color_black") #{user.firstName} #{user.lastName}
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile") a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw") i(class="fa fa-user fa-fw")
span(class="d-none d-md-inline") Benutzerprofil span(class="d-none d-md-inline") Benutzerprofil
if user.m4lab_idp == 1 if user.is_m4lab_idp
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/security") a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw") i(class="fa fa-lock fa-fw")
...@@ -40,7 +40,7 @@ html(lang="de") ...@@ -40,7 +40,7 @@ html(lang="de")
i(class="fa fa-tasks fa-fw") i(class="fa fa-tasks fa-fw")
span(class="d-none d-md-inline") Projekte und Dienste span(class="d-none d-md-inline") Projekte und Dienste
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;") a(class="nav-link pl-0 color_red" href="/logout")
i(class="fa fa-sign-out-alt fa-fw") i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1") main(class="col bg-faded py-3 flex-grow-1")
...@@ -60,13 +60,8 @@ html(lang="de") ...@@ -60,13 +60,8 @@ html(lang="de")
function verify() { function verify() {
$(".spinner-border").show() $(".spinner-border").show()
$.get( "/resendVerificationEmail", function( data ) { $.get( "/resendVerificationEmail", function( data ) {
console.log(data) if (data) { alert( "Email sent!" ) }
if (data) { else { alert("Please contact support-transfer@hft-stuttgart.de to verify your account.") }
alert( "Email sent!" )
}
else {
alert("Please contact support-transfer@hft-stuttgart.de to verify your account.")
}
}) })
.fail(function() { .fail(function() {
alert( "Something went wrong. Please try again." ) // todo: to DE alert( "Something went wrong. Please try again." ) // todo: to DE
......
doctype html
html(lang="de")
head
title= "Setup a new website"
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no")
link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css")
link(rel="stylesheet", type="text/css", href="/css/m4lab.css")
link(rel="stylesheet", href="https://use.fontawesome.com/releases/v5.8.2/css/all.css", integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay", crossorigin="anonymous")
body
div(class="container")
div(class="row min-vh-100 flex-column flex-md-row")
aside(class="col-12 col-md-3 p-0 flex-shrink-1")
nav(class="navbar navbar-expand flex-md-column flex-row align-items-start py-2")
div(class="collapse navbar-collapse")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="/account/")
span(class="font-weight-bold" style="color:black;") #{user.firstName} #{user.lastName}
li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw")
span(class="d-none d-md-inline") Benutzerprofil
if user.is_m4lab_idp
li(class="nav-item")
a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw")
span(class="d-none d-md-inline") Sicherheitseinstellungen
li(class="nav-item")
a(class="nav-link pl-0" href="/account/services")
i(class="fa fa-tasks fa-fw" style="color:black;")
span(class="d-none d-md-inline" style="color:black;") Projekte und Dienste
li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;")
i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1")
nav(aria-label="breadcrumb")
ol(class="breadcrumb")
li(class="breadcrumb-item")
a(href="/account/") Konto
li(class="breadcrumb-item")
a(href="/account/services") Projekte und Dienste
li(class="breadcrumb-item active" aria-current="page") Neue Projektinformation
if flash.success
div.alert.alert-success.alert-dismissible #{flash.success}
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if flash.error
div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
h3(class="pb-2") Neue Projektinformation
div(class="mx-4")
h4(class="pb-1") Schritt 1: Setup
p Bitte füllen Sie alle Felder aus
form(method="POST", encType="multipart/form-data")
div(class='form-group row')
label(for="template", class="col-sm-2") Template
div(class="col-sm-8")
select#templateSelector(name="template", class="form-control")
option(value="generic") generic
option(value="simple_raw") simple_raw
option(value="simple_thesis") simple_thesis
| <span id="templateExample" class="font-italic font-weight-light"><small>See the demo: <a href="https://transfer.hft-stuttgart.de/pages/athanasios.koukofikis/mygeneric/home/" target="_blank">generic</a>, <a href="https://transfer.hft-stuttgart.de/pages/athanasios.koukofikis/myraw/home/" target="_blank">simple_raw</a>, <a href="https://transfer.hft-stuttgart.de/pages/athanasios.koukofikis/mythesis/home/" target="_blank">simple_thesis</a></small></span>
div(class='form-group row')
label(for="name", class="col-sm-2") Name
div(class="col-sm-8")
input#name(name="name", type="text", class="form-control", placeholder="Name", maxlength="75" required)
p(id="nameInfo" class="font-italic font-weight-light") <small>Ihre Webseite wird unter folgender URL veröffentlicht: <strong>https://transfer.hft-stuttgart.de/pages/#{gitlabUsername}/<span id="websiteName"></span></strong></small>
div(class="form-group row")
label(for="description", class="col-sm-2") Beschreibung
div(class="col-sm-8")
textarea#description(name="description", type="text", class="form-control", placeholder="Beschreibung", maxlength="500" required)
div(class="form-group row")
label(for="logo", class="col-sm-2") Projektlogo
div(class="col-sm-8")
div(class="form-group row px-4")
- let defaultLogo = "https://m4lab.hft-stuttgart.de/img/footer/M4_LAB_LOGO_Graustufen.png"
img(src=defaultLogo, width="100" height="100")
div(class="form-group row px-3")
input#logo(name="logo", class="form-control-file", type="file")
p <small>(Max file size is 80 KB.)</small>
input(type="submit", class="btn btn-primary", value="Senden")
hr
div(class="mx-4", style="color: gray;")
h4(class="pb-1") Schritt 2: Dateneingabe
p Bitte stellen Sie sicher in GitLab, dass sie Folgendes abgeschlossen haben, bevor Sie Ihre Webseite veröffentlichen:
ol
li Bearbeiten Sie ihre <i>index.html</i>
li Anpassen der Einstellungen in <i>settings.js</i>
// jQuery
script(src="https://code.jquery.com/jquery-3.3.1.min.js")
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", crossorigin="anonymous")
// jquery-loading-overlay
script(src="https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@2.1.7/dist/loadingoverlay.min.js")
// Bootstrap
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous")
// M4_LAB
script(src="/js/headfoot.js")
script.
// website URL
function showWebsiteURL() {
if ($("#name").val()) {
$("#nameInfo").show()
let webName = $("#name").val().toLowerCase().replace(/\s/g, '-')
document.getElementById("websiteName").innerText = webName+"/home/"
}
else {
$("#nameInfo").hide()
}
}
$('#name').on('input',function(e){
showWebsiteURL()
})
showWebsiteURL()
$("form").submit(function(){
$.LoadingOverlay("show")
});
\ No newline at end of file
doctype html doctype html
html(lang="de") html(lang="de")
head head
title= "User Profile" title= "Benutzerprofil"
meta(charset="UTF-8") meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no") meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no")
link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css") link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css")
...@@ -16,12 +16,12 @@ html(lang="de") ...@@ -16,12 +16,12 @@ html(lang="de")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between") ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="/account/") a(class="nav-link pl-0 text-nowrap" href="/account/")
span(class="font-weight-bold" style="color:black;") #{user.firstname} #{user.lastname} span(class="font-weight-bold color_black") #{user.firstName} #{user.lastName}
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile") a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw" style="color:black;") i(class="fa fa-user fa-fw color_black")
span(class="d-none d-md-inline" style="color:black;") Benutzerprofil span(class="d-none d-md-inline color_black") Benutzerprofil
if user.m4lab_idp == 1 if user.is_m4lab_idp
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/security") a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw") i(class="fa fa-lock fa-fw")
...@@ -31,18 +31,24 @@ html(lang="de") ...@@ -31,18 +31,24 @@ html(lang="de")
i(class="fa fa-tasks fa-fw") i(class="fa fa-tasks fa-fw")
span(class="d-none d-md-inline") Projekte und Dienste span(class="d-none d-md-inline") Projekte und Dienste
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;") a(class="nav-link pl-0 color_red" href="/logout")
i(class="fa fa-sign-out-alt fa-fw") i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1") main(class="col bg-faded py-3 flex-grow-1")
if successes nav(aria-label="breadcrumb")
for success in successes ol(class="breadcrumb")
div.alert.alert-success.alert-dismissible #{ success } li(class="breadcrumb-item")
a(href="/account/") Konto
li(class="breadcrumb-item active" aria-current="page") Benutzerprofil
if flash.success
div.alert.alert-success.alert-dismissible #{flash.success}
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if errors if flash.error
for error, i in errors div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
div.alert.alert-danger.alert-dismissible.fade.show #{ error }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
h3(class="pb-2") Mein Profil
form#profileForm(method="POST", action="/updateProfile") form#profileForm(method="POST", action="/updateProfile")
div(class="form-row") div(class="form-row")
div(class='form-group col-md-2') div(class='form-group col-md-2')
...@@ -73,14 +79,14 @@ html(lang="de") ...@@ -73,14 +79,14 @@ html(lang="de")
} }
div(class='form-group col-md-2') div(class='form-group col-md-2')
label(for="firstname") Vorname label(for="firstname") Vorname
input#inputFirstname(name="inputFirstname", type="text", class="form-control", placeholder="Vorname", value=user.firstname, maxlength="45" required) input#inputFirstname(name="inputFirstname", type="text", class="form-control", placeholder="Vorname", value=user.firstName, maxlength="45" required)
div(class='form-group col-md-2') div(class='form-group col-md-2')
label(for="lastname") Nachname label(for="lastname") Nachname
input#inputLastname(name="inputLastname", type="text", class="form-control", placeholder="Nachname", value=user.lastname, maxlength="45" required) input#inputLastname(name="inputLastname", type="text", class="form-control", placeholder="Nachname", value=user.lastName, maxlength="45" required)
div(class="form-row") div(class="form-row")
div(class='form-group col-md-8') div(class='form-group col-md-8')
label(for="email") E-mail Adresse label(for="email") E-mail Adresse
input#inputEmail(name="inputEmail", type="email", class="form-control", placeholder="Email", value=email, maxlength="45" required) input#inputEmail(name="inputEmail", type="email", class="form-control", placeholder="Email", value=user.email, maxlength="45" required)
div(class="form-row") div(class="form-row")
div(class='form-group col-md-8') div(class='form-group col-md-8')
label(for="organisation") Unternehmen label(for="organisation") Unternehmen
......
...@@ -21,13 +21,11 @@ html(lang="de") ...@@ -21,13 +21,11 @@ html(lang="de")
div(class="alert alert-info" role="alert") div(class="alert alert-info" role="alert")
| Auf dieser Seite können sich Benutzer, die keinen Account an der HFT haben, registrieren.<br/> | Auf dieser Seite können sich Benutzer, die keinen Account an der HFT haben, registrieren.<br/>
| Um sich mit ihrem HFT-Account anzumelden, klicken Sie <a class="font-weight-bold" href="https://transfer.hft-stuttgart.de/account/">hier</a>. | Um sich mit ihrem HFT-Account anzumelden, klicken Sie <a class="font-weight-bold" href="https://transfer.hft-stuttgart.de/account/">hier</a>.
if successes if flash.success
for success in successes div.alert.alert-success.alert-dismissible #{flash.success}
div.alert.alert-success.alert-dismissible #{ success }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if errors if flash.error
for error, i in errors div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
div.alert.alert-danger.alert-dismissible.fade.show #{ error }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
form(method="POST") form(method="POST")
h5(class="pt-2 mb-3 font-weight-bold") Anmeldedaten h5(class="pt-2 mb-3 font-weight-bold") Anmeldedaten
......
...@@ -20,31 +20,29 @@ html(lang="de") ...@@ -20,31 +20,29 @@ html(lang="de")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between") ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="/account/") a(class="nav-link pl-0 text-nowrap" href="/account/")
span(class="font-weight-bold" style="color:black;") #{user.firstname} #{user.lastname} span(class="font-weight-bold color_black") #{user.firstName} #{user.lastName}
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile") a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw") i(class="fa fa-user fa-fw")
span(class="d-none d-md-inline") Benutzerprofil span(class="d-none d-md-inline") Benutzerprofil
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/security") a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw" style="color:black;") i(class="fa fa-lock fa-fw color_black")
span(class="d-none d-md-inline" style="color:black;") Sicherheitseinstellungen span(class="d-none d-md-inline color_black") Sicherheitseinstellungen
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/services") a(class="nav-link pl-0" href="/account/services")
i(class="fa fa-tasks fa-fw") i(class="fa fa-tasks fa-fw")
span(class="d-none d-md-inline") Projekte und Dienste span(class="d-none d-md-inline") Projekte und Dienste
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;") a(class="nav-link pl-0 color_red" href="/logout")
i(class="fa fa-sign-out-alt fa-fw") i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1") main(class="col bg-faded py-3 flex-grow-1")
if successes if flash.success
for success in successes div.alert.alert-success.alert-dismissible #{flash.success}
div.alert.alert-success.alert-dismissible #{ success }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if errors if flash.error
for error, i in errors div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
div.alert.alert-danger.alert-dismissible.fade.show #{ error }
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times; a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
form(class="needs-validation", method="post", action="/account/changePwd" novalidate) form(class="needs-validation", method="post", action="/account/changePwd" novalidate)
div(class="form-row") div(class="form-row")
......
...@@ -16,26 +16,76 @@ html(lang="de") ...@@ -16,26 +16,76 @@ html(lang="de")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between") ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="/") a(class="nav-link pl-0 text-nowrap" href="/")
span(class="font-weight-bold" style="color:black;") #{user.firstname} #{user.lastname} span(class="font-weight-bold color_black") #{user.firstName} #{user.lastName}
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile") a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw") i(class="fa fa-user fa-fw")
span(class="d-none d-md-inline") Benutzerprofil span(class="d-none d-md-inline") Benutzerprofil
if user.m4lab_idp == 1 if user.is_m4lab_idp
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/security") a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw") i(class="fa fa-lock fa-fw")
span(class="d-none d-md-inline") Sicherheitseinstellungen span(class="d-none d-md-inline") Sicherheitseinstellungen
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/account/services") a(class="nav-link pl-0" href="/account/services")
i(class="fa fa-tasks fa-fw" style="color:black;") i(class="fa fa-tasks fa-fw color_black")
span(class="d-none d-md-inline" style="color:black;") Projekte und Dienste span(class="d-none d-md-inline color_black") Projekte und Dienste
li(class="nav-item") li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;") a(class="nav-link pl-0 color_red" href="/logout")
i(class="fa fa-sign-out-alt fa-fw") i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1") main(class="col bg-faded py-3 flex-grow-1")
p Auf dieser Seite werden in Zukunft Funktionen bereitgestellt, um Ihre Beteiligung an Projekten und Aktivierung von Diensten zu organisieren. Diese Funktionen stehen zurzeit aber noch nicht zur Verfügung. nav(aria-label="breadcrumb")
ol(class="breadcrumb")
li(class="breadcrumb-item")
a(href="/account/") Konto
li(class="breadcrumb-item active" aria-current="page") Projekte und Dienste
div(class="container")
h3(class="pb-2") Dienste
div(class="col-sm-12")
//p Auf dieser Seite werden in Zukunft Funktionen bereitgestellt, um Ihre Beteiligung an Projekten und Aktivierung von Diensten zu organisieren. Diese Funktionen stehen zurzeit aber noch nicht zur Verfügung.
p Auf dieser Seite werden in Zukunft Funktionen bereitgestellt, um Ihre Aktivierung von Diensten zu organisieren. Diese Funktionen stehen zurzeit aber noch nicht zur Verfügung.
hr
div(class="container")
h3(class="pb-2") Projekte
div(class="col-sm-12")
if user.gitlabUserId
div(class="container")
div(class="row py-2 bg-light")
div(class="col font-weight-bold") Projektinformationen
div(class="col text-right")
a(href="/account/newInformation" class="btn btn-sm btn-success" role="button") Neue Projektinformation
table(class="table")
if gitlabPages.length == 0
tr
td Currently you have no project information
else
for item in gitlabPages
- let editNewPageLink = "/account/updateInformation?id="+item.projectInformation.id
- let websiteURL = "https://transfer.hft-stuttgart.de/pages/"+item.projectInformation.path+"/home/"
tr
td
img(src=item.projectInformation.logo, width="45", height="45")
td
a(href=editNewPageLink class="link-dark") #{item.projectInformation.name}
td
a(href=websiteURL class="link-dark" target="_blank") visit website
div(class="container")
div(class="row py-2 bg-light")
div(class="col font-weight-bold") Projektcode und -daten
div(class="col text-right")
button(type="button", class="btn btn-sm btn-success" disabled) Neuer Projektdatensatz
table(class="table")
for item in gitlabRepos
- let img = item.logo
tr
td
img(src=img, width="45", height="45")
td #{item.name}
else
p
| Bitte <a href="https://transfer.hft-stuttgart.de/gitlab" target="_blank">melden Sie sich an der Gitlab-Instanz an</a>, um Ihren Zugang zu aktivieren, und aktualisieren Sie diese Seite.
// jQuery // jQuery
script(src="https://code.jquery.com/jquery-3.3.1.min.js") script(src="https://code.jquery.com/jquery-3.3.1.min.js")
......
doctype html
html(lang="de")
head
title= "Update a website"
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no")
link(rel="stylesheet", type="text/css", href="/css/bootstrap.min.css")
link(rel="stylesheet", type="text/css", href="/css/m4lab.css")
link(rel="stylesheet", href="https://use.fontawesome.com/releases/v5.8.2/css/all.css", integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay", crossorigin="anonymous")
body
div(class="container")
div(class="row min-vh-100 flex-column flex-md-row")
aside(class="col-12 col-md-3 p-0 flex-shrink-1")
nav(class="navbar navbar-expand flex-md-column flex-row align-items-start py-2")
div(class="collapse navbar-collapse")
ul(class="flex-md-column flex-row navbar-nav w-100 justify-content-between")
li(class="nav-item")
a(class="nav-link pl-0 text-nowrap" href="/account/")
span(class="font-weight-bold" style="color:black;") #{user.firstName} #{user.lastName}
li(class="nav-item")
a(class="nav-link pl-0" href="/account/profile")
i(class="fa fa-user fa-fw")
span(class="d-none d-md-inline") Benutzerprofil
if user.is_m4lab_idp
li(class="nav-item")
a(class="nav-link pl-0" href="/account/security")
i(class="fa fa-lock fa-fw")
span(class="d-none d-md-inline") Sicherheitseinstellungen
li(class="nav-item")
a(class="nav-link pl-0" href="/account/services")
i(class="fa fa-tasks fa-fw" style="color:black;")
span(class="d-none d-md-inline" style="color:black;") Projekte und Dienste
li(class="nav-item")
a(class="nav-link pl-0" href="/logout" style="color:red;")
i(class="fa fa-sign-out-alt fa-fw")
span(class="d-none d-md-inline") Logout
main(class="col bg-faded py-3 flex-grow-1")
nav(aria-label="breadcrumb")
ol(class="breadcrumb")
li(class="breadcrumb-item")
a(href="/account/") Konto
li(class="breadcrumb-item")
a(href="/account/services") Projekte und Dienste
li(class="breadcrumb-item active" aria-current="page") Information aktualisieren
if flash.success
div.alert.alert-success.alert-dismissible #{flash.success}
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
if flash.error
div.alert.alert-danger.alert-dismissible.fade.show #{flash.error}
a(class="close", href="#", data-dismiss="alert", aria-label="close") &times;
h3(class="pb-2") Information aktualisieren
div(class="mx-4")
form(method="POST", encType="multipart/form-data")
div(class='form-group row')
label(for="name", class="col-sm-2") Name
div(class="col-sm-8")
input#name(name="name", type="text", class="form-control", value=information.name, placeholder="Name", maxlength="75" required)
div(class="form-group row")
label(for="description", class="col-sm-2") Beschreibung
div(class="col-sm-8")
textarea#description(name="description", type="text", class="form-control", placeholder="Beschreibung", maxlength="500" required) #{information.desc}
div(class="form-group row")
label(for="logo", class="col-sm-2") Projektlogo
div(class="col-sm-8")
div(class="form-group row")
img(src=information.logo, width="100" height="100")
div(class="form-group row")
input#logo(name="logo", class="form-control-file", type="file")
p <small>(Max file size is 80 KB.)</small>
input(type="submit", class="btn btn-primary", value="Speichern")
hr
div(class="mx-4")
p <b><i>[ANMERKUNG]</b></i> Bitte stellen Sie sicher in GitLab, dass sie Folgendes abgeschlossen haben, bevor Sie Ihre Webseite veröffentlichen:
div(class="help")
div(class="card")
- let indexLink = "https://transfer.hft-stuttgart.de/gitlab/"+information.path+"/-/edit/master/public/home/index.html"
- let settingLink = "https://transfer.hft-stuttgart.de/gitlab/"+information.path+"/-/edit/master/public/settings.js"
div(class="card-header")
div(class="card-title")
| <a class="collapsed" data-toggle="collapse" href="#collapse-index" aria-expanded="false" aria-controls="collapse-index">
| 1. Bearbeiten Sie ihre <i>index.html</i></a>
div(id="collapse-index" class="card-body collapse")
ol
li Klicken Sie <a href=#{indexLink} target="_blank"><i>hier</i></a>, um Ihre <i>index.html</i> in GitLab zu öffnen.
li Bearbeiten Sie ihre Datei.
li Um die Änderungen zu speichern und auf ihrer Seite sofort zu übernehmen, klicken Sie auf <i>Commit changes</i>
img(src="https://transfer.hft-stuttgart.de/img/help/save_file.png", class="img-fluid", style="border: 1px solid gray;", alt="index.html")
li Sobald Sie Änderungen an Ihrer <i>index.html</i> vornehmen, wird Ihre Website veröffentlicht.
div(class="card-header")
div(class="card-title")
| <a class="collapsed" data-toggle="collapse" href="#collapse-setting" aria-expanded="false" aria-controls="collapse-setting">2. Anpassen der Einstellungen in <i>settings.js</i></a>
div(id="collapse-setting" class="card-body collapse")
ol
li Klicken Sie <a href=#{settingLink} target="_blank"><i>settings.js</i></a>, um Ihre <i>settings.js</i> in GitLab zu öffnen.
li Bearbeiten Sie ihre Datei.
li Hier sehen Sie die Standardwerde für Soziale Netzwerke und persönliche Webseiten eines Teilnehmers sowie den Standardavatar. Es wird empfohlen, diese Werte nicht zu ändern, aber Sie können weitere Soziale Netzwerke hinzufügen.
img(src="https://transfer.hft-stuttgart.de/img/help/default_settings.png", class="img-fluid", style="border: 1px solid gray;")
li Diese Schalter kontrollieren, welche Teile der gitlab-Seite angezeigt werden sollen. Wenn Sie also beispielsweise nur eine einzige Seite haben, benötigen Sie kein Menü und können den Wert für 'menu' auf OFF stellen.
img(src="https://transfer.hft-stuttgart.de/img/help/switches.png", class="img-fluid", style="border: 1px solid gray;")
li Hier ändern Sie das Projektlogo. Das Logo wird am oberen Rand der Seite mittig angezeigt. Wenn der Schalter für 'project logo' auf OFF steht, wird es nicht angezeigt.
img(src="https://transfer.hft-stuttgart.de/img/help/pr_logo.png", class="img-fluid", style="border: 1px solid gray;")
li Hier ändern Sie das Menü Ihrer gitlab-Seite. Ein Menü kann entweder auf einen Unterordner/ template verweisen oder aber auf einen externen Link, z.B. eine Demo. Sie können Menüeinträge hinzufügen oder entfernen. Das Menü wird mit dem Schalter 'OFF' verborgen. Vergessen Sie nicht den Schrägstrich am Ende eines Menülinks, wenn dieser auf einen Ordner zeigt.
img(src="https://transfer.hft-stuttgart.de/img/help/menu.png", class="img-fluid", style="border: 1px solid gray;")
li Hier ändern Sie die Teilnehmenden. Sie können die Standardwerte für Soziale Netzwerke (diese beinhalten die HFT-Kanäle) oder Ihr eigenen Profile verwenden. Sie können auf Ihre persönliche Webseite verlinken. Sie können soziale Netzwerke hinzufügen oder entfernen. Sie können auch einen persönlichen Avatar oder den Standard-Avatar (DEFAULT.avatar) verwenden.
img(src="https://transfer.hft-stuttgart.de/img/help/partic.png", class="img-fluid", style="border: 1px solid gray;")
li Hier ist ein Beispiel mit zwei Teilnehmenden:
img(src="https://transfer.hft-stuttgart.de/img/help/partic2.png", class="img-fluid", style="border: 1px solid gray;")
li Hier ändern Sie die Fußzeilenlogos z.B. zu denen von Projektpartnern. Wenn Sie das Logo nicht mit einer externen Webseite verlinken wollen, verwenden Sie EMPTY_LINK als Wert für href. Der Titel title wird bei Mouse-Hover über dem Logo erscheinen.
img(src="https://transfer.hft-stuttgart.de/img/help/f_logos.png", class="img-fluid", style="border: 1px solid gray;")
li Klicken Sie anschließend auf <i>Commit changes</i>, um die Änderungen zu speichern.
img(src="https://transfer.hft-stuttgart.de/img/help/edit_settings_generic.png", class="img-fluid", style="border: 1px solid gray;")
hr
div(class="mx-4")
div(class="alert alert-danger" role="alert") <h5><strong>Webseite löschen</strong></h5>
p Dies wird <strong><em>#{information.name}</em></strong> sofort endgültig löschen, inklusive ihrer Repositorien und aller zugehöriger Ressourcen.
p Sind Sie WIRKLICH SICHER, dass Sie diese Webseite löschen wollen?
button(type="button" class="btn btn-danger" data-toggle="modal" data-target="#deleteWebsiteConfirmation") Löschen
// Modal
div(class="modal" id="deleteWebsiteConfirmation" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true")
div(class="modal-dialog" role="document")
div(class="modal-content")
div(class="modal-header")
h5(class="modal-title" id="modalLabel") Sind Sie WIRKLICH SICHER?
button(type="button" class="close" data-dismiss="modal" aria-label="Close")
span(aria-hidden="true") &times;
div(class="modal-body")
| <p>Sie sind dabei, diese Webseite, ihr Repositorium und alle zugehörigen Ressourcen, inklusive aller Inhalte, Bilder etc. endgültig zu löschen.</p>
| <p>Sobald eine Webseite endgültig gelöscht ist, kann sie nicht wiederhergestellt werden. <strong>Diese Aktion kann nicht rückgängig gemacht werden.</strong></p>
div(class="modal-footer")
form(method="POST", action="/deleteProject?_method=DELETE", encType="multipart/form-data")
input(name="id", value=information.id, type="hidden")
button(type="button" class="btn btn-primary mx-2" data-dismiss="modal") Abbrechen, Webseite behalten
button(type="submit" class="btn btn-danger") Ja, Webseite löschen
// jQuery
script(src="https://code.jquery.com/jquery-3.3.1.min.js")
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js", integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1", crossorigin="anonymous")
// jquery-loading-overlay
script(src="https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@2.1.7/dist/loadingoverlay.min.js")
// Bootstrap
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous")
// M4_LAB
script(src="/js/headfoot.js")
script.
function sendPublishRequest() {
$.post("/sendPublishRequest", {projectName: $("#name").val()}, function(resp){
alert(resp)
})
}
$("form").submit(function(){
$.LoadingOverlay("show")
});
\ No newline at end of file
...@@ -22,15 +22,15 @@ html(lang="de") ...@@ -22,15 +22,15 @@ html(lang="de")
body body
div(class="container") div(class="container")
div(class="center", align="center") div(class="center", align="center")
a(href="https://m4lab.hft-stuttgart.de") a(href="https://transfer.hft-stuttgart.de")
img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192") img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
br br
br br
if status == true if status == true
p(class="h5") Ihr Benutzerkonto wurde bestätigt. Bitte <a href="https://m4lab.hft-stuttgart.de/account/">melden Sie sich an</a>. p(class="h5") Ihr Benutzerkonto wurde bestätigt. Bitte <a href="https://transfer.hft-stuttgart.de/account/">melden Sie sich an</a>.
else if status == false else if status == false
p(class="h5") Ihr Benutzerkonto konnte nicht bestätigt werden, bitte versuchen Sie es erneut. p(class="h5") Ihr Benutzerkonto konnte nicht bestätigt werden, bitte versuchen Sie es erneut.
else else
p(class="h5") Ihr Benutzerkonto wude nicht gefunden. p(class="h5") Ihr Benutzerkonto wurde nicht gefunden.
// Bootstrap // Bootstrap
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous") script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous")
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment