Commit 637a9675 authored by Wolfgang Knopki's avatar Wolfgang Knopki
Browse files

Merge branch 'testing' into prepare_prod

parents fe1cf482 c8891053
This diff is collapsed.
......@@ -16,7 +16,9 @@
"url": "https://transfer.hft-stuttgart.de/gitlab/m4lab_tv1/user-account.git"
},
"scripts": {
"start": "nodemon app.js",
"start": "nodemon app.ts",
"build": "tsc -build",
"clean": "tsc -build --clean",
"test": "jest"
},
"dependencies": {
......@@ -26,20 +28,17 @@
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"cookie-parser": "1.4.3",
"crypto": "^1.0.1",
"errorhandler": "1.4.3",
"dotenv": "^9.0.2",
"express": "^4.17.1",
"express-fileupload": "^1.1.6",
"express-flash-2": "^1.0.1",
"express-session": "^1.17.0",
"form-data": "^3.0.0",
"fs": "0.0.1-security",
"helmet": "^3.23.3",
"i18n": "^0.8.5",
"jest": "^26.6.3",
"helmet": "^4.6.0",
"jest": "^26.5.0",
"method-override": "^3.0.0",
"morgan": "^1.9.1",
"mysql": "^2.17.1",
"mysql2": "^2.2.5",
"nodemailer": "^6.3.1",
"nodemailer-ntlm-auth": "^1.0.1",
......@@ -48,7 +47,26 @@
"pug": "^3.0.2"
},
"devDependencies": {
"nodemon": "^2.0.1"
"@types/async": "^3.2.6",
"@types/bcryptjs": "^2.4.2",
"@types/compression": "^1.7.0",
"@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.11",
"@types/express-fileupload": "^1.1.6",
"@types/express-flash-2": "^1.0.6",
"@types/express-session": "^1.17.0",
"@types/jest": "^26.0.23",
"@types/method-override": "^0.0.31",
"@types/morgan": "^1.9.2",
"@types/mysql": "^2.15.18",
"@types/node": "^15.0.2",
"@types/nodemailer": "^6.4.1",
"@types/passport": "^1.0.6",
"@types/passport-strategy": "^0.2.35",
"@types/xml2js": "^0.4.8",
"nodemon": "^2.0.1",
"ts-node": "^9.1.1",
"typescript": "^4.2.4"
},
"engines": {
"node": ">= 4.0.0"
......
/* German initialisation for the jQuery UI date picker plugin. */
/* Written by Milian Wolff (mail@milianw.de). */
( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [ "../widgets/datepicker" ], factory );
} else {
// Browser globals
factory( jQuery.datepicker );
}
}( function( datepicker ) {
datepicker.regional.de = {
closeText: "Schließen",
prevText: "<Zurück",
nextText: "Vor>",
currentText: "Heute",
monthNames: [ "Januar","Februar","März","April","Mai","Juni",
"Juli","August","September","Oktober","November","Dezember" ],
monthNamesShort: [ "Jan","Feb","Mär","Apr","Mai","Jun",
"Jul","Aug","Sep","Okt","Nov","Dez" ],
dayNames: [ "Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag" ],
dayNamesShort: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
dayNamesMin: [ "So","Mo","Di","Mi","Do","Fr","Sa" ],
weekHeader: "KW",
dateFormat: "dd.mm.yy",
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: "" };
datepicker.setDefaults( datepicker.regional.de );
return datepicker.regional.de;
} ) );
\ No newline at end of file
This diff is collapsed.
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
import async from 'async'
import bcrypt from 'bcryptjs'
import methods from '../functions/methods'
import mailer from '../config/mailer'
import constants from '../config/const'
const saltRounds:number = 10
const salt:number = 64
export = function (app:any, config:any, lang:string) {
// ================== NEW USERS REGISTRATION ======================
app.get('/registration', function(req:any, res:any) {
res.render(lang+'/account/registration')
})
app.post('/registration', function(req:any, res:any) {
// user data
var curDate:Date = new Date()
var userData:any = {
salutation: req.body.inputSalutation,
title: req.body.inputTitle,
firstname: req.body.inputFirstname,
lastname: req.body.inputLastname,
email: req.body.inputEmail,
organisation: req.body.inputOrganisation,
industry: req.body.inputIndustry,
speciality: req.body.inputSpeciality,
createdDate: curDate.toISOString().slice(0,10)
}
var userEmail:any = userData.email
var pos:number = userEmail.indexOf('@')
var emailLength:number = userEmail.length
var emailDomain:any = userEmail.slice(pos, emailLength);
if ( emailDomain.toLowerCase() == "@hft-stuttgart.de") {
res.flash('error', "Fehlgeschlagen: HFT-Account")
res.redirect('/account/registration')
} else {
async.waterfall([
function(done:any) {
// generate token
let token:string = '';
let randomChars:string = 'abcdefghijklmnopqrstuvwxyz0123456789';
for ( let i = 0; i<40; i++ ) {
token += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
}
// encrypt password
bcrypt.genSalt(saltRounds, function(err, salt) {
bcrypt.hash(req.body.inputPassword, salt, function(err:any, hash:any) {
var newAccount:any = {
profile: userData,
password: hash,
verificationToken: token
}
done(err, newAccount)
});
});
},
// save data
function(newAccount:any, err:any) {
methods.registerNewUser(newAccount, function(err:any){
if (err) {
res.flash('error', "Fehlgeschlagen")
}
else {
// send email
var emailSubject = "Bitte bestätigen Sie Ihr M4_LAB Benutzerkonto"
var emailContent = '<div>Lieber Nutzer,<br/><br/>' +
'<p>vielen Dank für Ihre Anmeldung am Transferportal der HFT Stuttgart. <br/>' +
'Um Ihre Anmeldung zu bestätigen, klicken Sie bitte <a href='+config.app.host+'/verifyAccount?token='+newAccount.verificationToken+'>diesen Link</a> ' +
'<br/><br/>' +
'Ohne Bestätigung Ihres Kontos müssen wir Ihr Konto leider nach 7 Tagen löschen.</p><br/>' + constants.mailSignature +
'</div>';
mailer.options.to = req.body.inputEmail;
mailer.options.subject = emailSubject;
mailer.options.html = emailContent;
mailer.transporter.sendMail(mailer.options, function(err:any) {
if (err) {
console.error('Cannot send email. [Error] '+err)
throw err
}
})
// user feedback
res.flash('success', 'Vielen Dank für Ihre Registrierung!'+'\r\n\r\n'+
'Wir haben Ihnen eine E-Mail an Ihre verwendete Adresse gesendet. Diese enthält einen Link zur Bestätigung Ihres Accounts.'+'\r\n'+
'Wenn Sie die Mail nicht in ihrem Postfach vorfinden, prüfen Sie bitte auch Ihren Spam-Ordner.')
}
res.redirect('/account/registration')
})
}
])
}
})
// to check whether or not an account is already exist
app.get('/email/:email', async function(req:any, res:any) {
let user = await methods.checkUserEmail(req.params.email)
if (!user) {
console.log('No user found: '+req.params.email)
res.send(true)
} else {
console.log('User found: '+req.params.email)
res.send(false)
}
})
// =================== USERS VERIFICATION =========================
app.get("/verifyAccount", async function(req:any, res:any){
let userId:number = await methods.getUserIdByVerificationToken(req.query.token)
if (!userId) {
// no user found
res.render(lang+'/account/verification', {
status: null
})
} else {
// a user found, verify the account
let userData:any = {
id: userId,
verificationStatus: 1
}
methods.verifyUserAccount(userData, async function(err:any){
if (err) {
console.log("Error: "+err)
res.render(lang+'/account/verification', {
status: false
});
} else {
// send welcome email after successful account verification
let userEmail:string = await methods.getUserEmailById(userId)
if (!userEmail) {
res.render(lang+'/account/verification', {
status: false
})
} else {
// send email
var emailSubject = "Herzlich willkommen"
var emailContent = '<div>Lieber Nutzer,<br/><br/>' +
'<p>herzlich willkommen beim Transferportal der HFT Stuttgart!<br/>' +
'Sie können nun alle Dienste des Portals nutzen.<p/><br/>' + constants.mailSignature;
mailer.options.to = userEmail
mailer.options.subject = emailSubject
mailer.options.html = emailContent
mailer.transporter.sendMail(mailer.options, function(err:any) {
if (err) {
console.log('cannot send email')
throw err
}
})
res.render(lang+'/account/verification', {
status: true
})
}
}
})
}
})
// ==================== FORGOT PASSWORD ===========================
app.get('/forgotPwd', function (req:any, res:any) {
res.render(lang+'/account/forgotPwd', {
user: req.user
})
})
app.post('/forgotPwd', function(req:any, res:any) {
let emailAddress = req.body.inputEmail
async.waterfall([
async function(done:any) {
let user = await methods.checkUserEmail(emailAddress)
if (!user) {
console.log('No user found: '+emailAddress)
} else {
// generate token
let token:string = '';
let randomChars:string = 'abcdefghijklmnopqrstuvwxyz0123456789';
for ( let i = 0; i<40; i++ ) {
token += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
}
var emailSubject = "Ihre Passwort-Anfrage an das Transferportal der HFT Stuttgart";
var emailContent = '<div>Lieber Nutzer,<br/><br/>' +
'<p>wir haben Ihre Anfrage zur Erneuerung Ihres Passwortes erhalten. Falls Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese E-Mail.<br/><br/>' +
'Sie können Ihr Passwort mit dem Klick auf diesen Link ändern: '+config.app.host+'/reset/' + token + '<br/>' +
'Dieser Link ist aus Sicherheitsgründen nur für 1 Stunde gültig.<br/></p>' + constants.mailSignature + '</div>'
var credentialData = {
user_id: user.id,
resetPasswordToken: token,
resetPasswordExpires: Date.now() + 3600000 // 1 hour
}
let result = await methods.updateCredential(credentialData)
if (!result) {
console.log('failed to update credential')
} else {
// send email
mailer.options.to = emailAddress
mailer.options.subject = emailSubject
mailer.options.html = emailContent
mailer.transporter.sendMail(mailer.options, function(err:any) {
if (err) { console.error(err) }
})
}
}
done(null)
}
], function(err:any) {
if (err) {
res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.')
}
else {
res.flash('success', 'Wenn Ihre E-Mail-Adresse registriert ist, wurde eine E-Mail mit dem weiteren Vorgehen an ' + emailAddress + ' versendet.')
}
res.redirect('/account/forgotPwd')
})
})
// reset
app.get('/reset/:token', async function(req:any, res:any) {
let user = await methods.getUserByToken(req.params.token)
if (!user) {
res.flash('error', 'Der Schlüssel zum zurücksetzen des Passworts ist ungültig oder abgelaufen.')
res.redirect('/account/forgotPwd')
} else {
res.render(lang+'/account/reset')
}
})
app.post('/reset/:token', async function(req:any, res:any) {
var newPwd = req.body.inputNewPwd
var user = await methods.getUserByToken(req.params.token)
if (!user) {
res.flash('error', "User not found.")
res.redirect('/login')
} else {
// encrypt password
bcrypt.genSalt(saltRounds, function(err, salt) {
bcrypt.hash(newPwd, salt, async function(err:any, hash) {
var credentialData = {
password: hash,
user_id: user.user_id
}
// update password
let result = await methods.updateCredential(credentialData)
if (!result) {
console.log('Failed to reset password')
res.flash('error', "Datenbankfehler: Passwort kann nicht geändert werden.")
} else {
res.flash('success', "Passwort aktualisiert!")
// send notifiaction email
mailer.options.to = user.email
mailer.options.subject = constants.updatePasswordMailSubject
mailer.options.html = constants.updatePasswordMailContent+'<div>'+constants.mailSignature+'</div>'
mailer.transporter.sendMail(mailer.options, function(err:any) {
if (err) { console.log(err) }
})
}
res.redirect('/login')
});
});
}
})
// ======================= CONTACT FORM ===========================
app.get('/contact', function (req:any, res:any) {
res.render(lang+'/account/contact', {
user: req.user
})
})
app.post('/contact', function(req:any, res:any, next:any) {
//methods.currentDate();
let emailAddress = req.body.inputEmail;
let supportAddress = "support-transfer@hft-stuttgart.de";
let inputName = req.body.name;
let inputContent = req.body.message;
let emailContent = "Es wurde eine Anfrage an das Transferportal gestellt: \n\n NAME: " + inputName + "\n NACHRICHT:\n "+ inputContent;
let emailSubject = "Ihre Anfrage an das Transferportal";
async.waterfall([
function(done:any) {
// send email
mailer.options.to = supportAddress;
mailer.options.cc = emailAddress;
mailer.options.subject = emailSubject;
mailer.options.text = emailContent;
mailer.transporter.sendMail(mailer.options, function(err:any) {
done(err, 'done');
});
}
], function(err:any) {
if (err) {
console.error(err)
res.flash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
}
else {
res.flash('success', 'Vielen Dank für Ihre Anfrage. Wir melden uns baldmöglichst bei Ihnen. Eine Kopie Ihrer Anfrage wurde an ' + emailAddress + ' versandt.');
}
res.redirect('/account/contact')
})
})
}
\ No newline at end of file
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"rootDir": "./",
"outDir": "./built",
"esModuleInterop": true,
"strict": true,
"allowJs": true
}
}
\ No newline at end of file
......@@ -21,8 +21,8 @@ html(lang="de")
body
div(class="container")
div(class="center", align="center")
a(href="https://m4lab.hft-stuttgart.de")
img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
a(href="/")
img(src="/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
br
br
p(class="h5") 404. The requested URL was not found.
......
......@@ -21,8 +21,8 @@ html(lang="de")
body
div(class="container")
div(class="center", align="center")
a(href="https://m4lab.hft-stuttgart.de")
img(src="https://transfer.hft-stuttgart.de/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
a(href="/")
img(src="/images/demo/m4lab_logo.jpg", class="img-responsive center-block", width="185", height="192")
br
br
p(class="h5") 500. Unexpected Error :(
......
......@@ -76,7 +76,7 @@ html(lang="de")
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"
- let defaultLogo = "/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")
......
......@@ -85,7 +85,7 @@ html(lang="de")
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")
img(src="/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")
......@@ -95,21 +95,21 @@ html(lang="de")
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;")
img(src="/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;")
img(src="/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;")
img(src="/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;")
img(src="/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;")
img(src="/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;")
img(src="/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;")
img(src="/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;")
img(src="/img/help/edit_settings_generic.png", class="img-fluid", style="border: 1px solid gray;")
hr
div(class="mx-4")
......
doctype html
html
head
title PassportJS SAML example
block links
link(rel='stylesheet', href='bower_components/bootstrap/dist/css/bootstrap.css')
body
div.container
block content
script(src='bower_components/jquery/dist/jquery.min.js')
script(src='bower_components/bootstrap/dist/js/bootstrap.min.js')
block scripts
Markdown is supported
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