Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
m4lab_tv1
User Account
Commits
69ab56ca
Commit
69ab56ca
authored
Dec 04, 2019
by
Rosanny Sihombing
Browse files
Initial commit
parents
Pipeline
#311
failed with stages
in 28 seconds
Changes
36
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
routes/methods.js
0 → 100644
View file @
69ab56ca
const
dbconn
=
require
(
'
./dbconn
'
);
var
methods
=
{
// test method
currentDate
:
function
()
{
console
.
log
(
'
Current Date is:
'
+
new
Date
().
toISOString
().
slice
(
0
,
10
));
},
// ======================= user db =======================
checkUserEmail
:
function
(
email
,
callback
)
{
var
user
;
dbconn
.
user
.
query
(
'
SELECT email FROM user WHERE email = "
'
+
email
+
'
"
'
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
{
throw
err
;
}
else
{
if
(
rows
.
length
>
0
)
{
user
=
rows
[
0
];
}
}
callback
(
err
,
user
);
});
},
checkUserToken
:
function
(
token
,
callback
)
{
var
user
;
dbconn
.
user
.
query
(
'
SELECT email FROM user WHERE resetPasswordToken = "
'
+
token
+
'
" and resetPasswordExpires >
'
+
Date
.
now
(),
function
(
err
,
rows
,
fields
)
{
if
(
err
)
{
throw
err
;
}
else
{
if
(
rows
.
length
>
0
)
{
user
=
rows
[
0
];
}
}
callback
(
err
,
user
);
});
},
updateUser
:
function
(
userData
,
callback
)
{
dbconn
.
user
.
query
(
'
UPDATE user SET ? WHERE email = "
'
+
userData
.
email
+
'
"
'
,
userData
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
throw
err
;
callback
(
err
);
})
},
updatePassword
:
function
(
hash
,
email
,
callback
)
{
dbconn
.
user
.
query
(
'
UPDATE user SET password = "
'
+
hash
+
'
" WHERE email = "
'
+
email
+
'
"
'
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
throw
err
;
callback
(
err
);
})
},
getUserIdByEmail
:
function
(
email
,
callback
)
{
var
userId
dbconn
.
user
.
query
(
'
SELECT id FROM user WHERE email = "
'
+
email
+
'
"
'
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
{
throw
err
;
}
else
{
if
(
rows
.
length
>
0
)
{
userId
=
rows
[
0
].
id
;
}
}
callback
(
userId
,
err
);
});
},
getUserProjectRole
:
function
(
userId
,
callback
)
{
dbconn
.
user
.
query
(
'
SELECT project_id, role_id FROM user_project_role WHERE user_id = "
'
+
userId
+
'
"
'
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
throw
err
;
callback
(
rows
,
err
);
});
},
// ======================= project db =======================
getAllProjects
:
function
(
callback
)
{
dbconn
.
project
.
query
(
'
CALL getAllprojects
'
,
function
(
err
,
rows
,
fields
){
if
(
err
)
throw
err
;
callback
(
rows
[
0
],
err
);
})
}
};
module
.
exports
=
methods
;
\ No newline at end of file
routes/routes.js
0 → 100644
View file @
69ab56ca
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
;
// forgot pwd
const
async
=
require
(
'
async
'
);
const
crypto
=
require
(
'
crypto
'
);
const
nodemailer
=
require
(
'
nodemailer
'
);
module
.
exports
=
function
(
app
,
config
,
passport
)
{
// =========== 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
);
// ============================
/*
app.all('/', function(req, res){
req.flash('test', 'it worked');
res.redirect('/test')
});
app.all('/test', function(req, res){
res.send(JSON.stringify(req.flash('test')));
});
*/
app
.
get
(
'
/
'
,
function
(
req
,
res
)
{
res
.
redirect
(
'
/profile
'
)
});
app
.
get
(
'
/login
'
,
passport
.
authenticate
(
config
.
passport
.
strategy
,
{
successRedirect
:
'
/
'
,
failureRedirect
:
'
/login
'
})
);
app
.
post
(
config
.
passport
.
saml
.
path
,
passport
.
authenticate
(
config
.
passport
.
strategy
,
{
failureRedirect
:
'
/
'
,
failureFlash
:
true
}),
function
(
req
,
res
)
{
res
.
redirect
(
'
/
'
);
}
);
app
.
get
(
'
/profile
'
,
function
(
req
,
res
)
{
if
(
req
.
isAuthenticated
())
{
res
.
render
(
'
profile
'
,
{
user
:
req
.
user
// useful for view engine, useless for HTML
});
}
else
{
res
.
redirect
(
'
/login
'
);
}
});
app
.
get
(
'
/services
'
,
function
(
req
,
res
)
{
if
(
req
.
isAuthenticated
())
{
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
=
"
You cannot access this service
"
if
(
userProjectId
.
indexOf
(
projectsOverview
[
i
].
id
)
>
-
1
)
{
status
=
"
You can access this service
"
}
// 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
(
'
services
'
,
{
user
:
req
.
user
,
project
:
allProjects
});
}
])
}
else
{
res
.
redirect
(
'
/login
'
);
}
});
app
.
get
(
'
/security
'
,
function
(
req
,
res
)
{
if
(
req
.
isAuthenticated
())
{
res
.
render
(
'
security
'
,
{
user
:
req
.
user
// useful for view engine, useless for HTML
});
}
else
{
res
.
redirect
(
'
/login
'
);
}
});
app
.
post
(
'
/updateProfile
'
,
function
(
req
,
res
)
{
var
userData
=
{
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
.
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!
'
);
}
res
.
redirect
(
'
/profile
'
);
})
}
}
else
{
res
.
redirect
(
'
/login
'
);
}
});
// todo: user registration with captcha
app
.
post
(
'
/changePwd
'
,
function
(
req
,
res
)
{
if
(
req
.
isAuthenticated
())
{
var
currPwd
=
req
.
body
.
inputCurrPwd
var
newPwd
=
req
.
body
.
inputNewPwd
var
retypePwd
=
req
.
body
.
inputConfirm
// Load hashed passwd from DB.
dbconn
.
query
(
'
SELECT password FROM user WHERE email="
'
+
req
.
user
.
email
+
'
"
'
,
function
(
err
,
rows
,
fields
)
{
if
(
err
)
{
res
.
redirect
(
'
/500
'
)
throw
err
}
var
userPwd
=
rows
[
0
].
password
// check if the password is correct
bcrypt
.
compare
(
currPwd
,
userPwd
,
function
(
err
,
isMatch
)
{
if
(
err
)
{
res
.
redirect
(
'
/500
'
)
throw
err
}
else
if
(
!
isMatch
)
{
req
.
flash
(
'
error
'
,
"
Sorry, your password was incorrect. Please double-check your password.
"
)
res
.
redirect
(
'
/security
'
)
}
else
{
if
(
newPwd
!=
retypePwd
)
{
req
.
flash
(
'
error
'
,
"
Passwords do no match. Please make sure you re-type your new password correctly.
"
)
res
.
redirect
(
'
/security
'
)
}
else
{
// update password
bcrypt
.
genSalt
(
saltRounds
,
function
(
err
,
salt
)
{
bcrypt
.
hash
(
newPwd
,
salt
,
function
(
err
,
hash
)
{
methods
.
updatePassword
(
hash
,
req
.
user
.
email
,
function
(
err
){
if
(
err
)
{
req
.
flash
(
'
error
'
,
"
Database error: Password cannot be modified.
"
)
throw
err
}
else
{
req
.
flash
(
'
success
'
,
"
Pasword updated!
"
)
console
.
log
(
'
pasword updated!
'
)
}
res
.
redirect
(
'
/security
'
)
})
});
});
}
}
})
})
}
else
{
res
.
redirect
(
'
/login
'
);
}
});
app
.
get
(
'
/forgotPwd
'
,
function
(
req
,
res
)
{
res
.
render
(
'
forgotPwd
'
,
{
user
:
req
.
user
});
/*
if email found: send generated email or instruction to reset password
if email not found: send notification, example: https://www.troyhunt.com/everything-you-ever-wanted-to-know/
*/
});
var
smtpTransport
=
nodemailer
.
createTransport
({
host
:
config
.
mailer
.
host
,
secureConnection
:
config
.
mailer
.
secureConnection
,
port
:
config
.
mailer
.
port
,
auth
:
{
user
:
config
.
mailer
.
authUser
,
pass
:
config
.
mailer
.
authPass
},
tls
:
{
ciphers
:
config
.
mailer
.
tlsCiphers
}
});
var
mailOptions
=
{
to
:
""
,
from
:
config
.
mailer
.
from
,
subject
:
""
,
text
:
""
};
app
.
post
(
'
/forgotPwd
'
,
function
(
req
,
res
,
next
)
{
//methods.currentDate();
/* do something: write down reset password procedure in Technical Req. Document
ref: https://meanstackdeveloper.in/implement-reset-password-functionality-in-node-js-express.html
https://medium.com/@terrychayes/adding-password-reset-functionality-to-a-react-app-with-a-node-backend-4681480195d4
http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/
if email found: send generated email or instruction to reset password
if email not found: send notification, example: https://www.troyhunt.com/everything-you-ever-wanted-to-know/
*/
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,
\n
M4_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
"
);
emailSubject
=
"
M4_LAB Password Reset
"
;
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://
"
+
req
.
headers
.
host
+
"
/reset/
"
+
token
+
"
\n
"
+
"
This password reset is only valid for 1 hour.
\n\n
"
+
"
Thanks,
\n
M4_LAB Team
"
user
.
resetPasswordToken
=
token
;
user
.
resetPasswordExpires
=
Date
.
now
()
+
3600000
;
// 1 hour
methods
.
updateUser
(
user
,
function
(
err
)
{
done
(
err
,
token
,
user
);
});
}
else
{
done
(
err
,
null
,
null
);
}
});
},
function
(
token
,
user
,
done
)
{
mailOptions
.
to
=
emailAddress
;
mailOptions
.
subject
=
emailSubject
;
mailOptions
.
text
=
emailContent
;
smtpTransport
.
sendMail
(
mailOptions
,
function
(
err
)
{
done
(
err
,
'
done
'
);
});
}
],
function
(
err
)
{
if
(
err
)
{
req
.
flash
(
'
error
'
,
'
An error occured. Please try again.
'
);
}
else
{
req
.
flash
(
'
success
'
,
'
An e-mail has been sent to
'
+
emailAddress
+
'
with further instructions.
'
);
}
res
.
redirect
(
'
/forgotPwd
'
);
});
});
app
.
get
(
'
/reset/:token
'
,
function
(
req
,
res
)
{
methods
.
checkUserToken
(
req
.
params
.
token
,
function
(
err
,
user
){
//console.log(user);
if
(
!
user
)
{
req
.
flash
(
'
error
'
,
'
Password reset token is invalid or has expired.
'
);
res
.
redirect
(
'
/forgotPwd
'
);
}
else
{
res
.
render
(
'
reset
'
);
}
});
});
app
.
post
(
'
/reset/:token
'
,
function
(
req
,
res
)
{
methods
.
checkUserToken
(
req
.
params
.
token
,
function
(
err
,
user
){
if
(
user
)
{
// update password
bcrypt
.
genSalt
(
saltRounds
,
function
(
err
,
salt
)
{
bcrypt
.
hash
(
req
.
params
.
inputNewPwd
,
salt
,
function
(
err
,
hash
)
{
methods
.
updatePassword
(
hash
,
user
.
email
,
function
(
err
){
if
(
err
)
{
req
.
flash
(
'
error
'
,
"
Database error: Password cannot be modified.
"
)
throw
err
}
else
{
req
.
flash
(
'
success
'
,
"
Your pasword has been updated.
"
)
console
.
log
(
'
pasword updated!
'
)
// todo: send confirmation email
}
})
});
});
}
else
{
req
.
flash
(
'
error
'
,
"
User not found.
"
)
}
});
res
.
redirect
(
'
/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
);
});
});
// 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
);
}
);
};
views/404.pug
0 → 100644
View file @
69ab56ca
extends error
block content
h2 Cannot find #{url}
\ No newline at end of file
views/500.pug
0 → 100644
View file @
69ab56ca
extends error
block content
h1 Error: #{error.message}
if settings['verbose errors']
pre= error.stack
else
p An error ocurred!
\ No newline at end of file
views/TBD/profile-old.html
0 → 100644
View file @
69ab56ca
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<title>
User Profile
</title>
<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=
"https://transfer.hft-stuttgart.de/css/bootstrap/bootstrap.css"
/>
<link
rel=
"stylesheet"
href=
"https://use.fontawesome.com/releases/v5.8.2/css/all.css"
integrity=
"sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay"
crossorigin=
"anonymous"
/>
<style>
.collapse
{
display
:
none
;
}
.collapse.in
{
display
:
block
;
}
.collapsing
{
position
:
relative
;
height
:
0
;
overflow
:
hidden
;
-webkit-transition-timing-function
:
ease
;
-o-transition-timing-function
:
ease
;
transition-timing-function
:
ease
;
-webkit-transition-duration
:
.35s
;
-o-transition-duration
:
.35s
;
transition-duration
:
.35s
;
-webkit-transition-property
:
height
,
visibility
;
-o-transition-property
:
height
,
visibility
;
transition-property
:
height
,
visibility
;
}
</style>
</head>
<body>
<!-- CONTENT -->
<div
class=
"container-fluid"
>
<div
class=
"row"
>
<!-- https://getbootstrap.com/docs/4.3/components/navs/ -->
<div
class=
"col-3"
>
<h5>
<span
id=
"fullname"
></span>
</h5>
<div
class=
"nav flex-column nav-pills"
id=
"v-pills-tab"
role=
"tablist"
aria-orientation=
"vertical"
>
<a
class=
"nav-link"
href=
"#"
aria-selected=
"true"
>
Profile
</a>
<a
class=
"nav-link"
href=
"/security"
aria-selected=
"false"
>
Security
</a>
<a
class=
"nav-link"
href=
"#"
aria-selected=
"false"
>
Services
</a>
</div>
</div>
<div
class=
"col-sm-9"
>
<form
id=
"profileForm"
method=
"POST"
action=
"/updateProfile"
>
<!-- p><input type="hidden" th:value="${id}"/></p -->
<table
class=
"table table-borderless"
>
<tr>
<th><label
for=
"title"
>
Title
</label></th>
<td><input
id=
"inputTitle"
name=
"inputTitle"
type=
"text"
placeholder=
"Title"
></td>
</tr>
<tr>
<th><label
for=
"firstname"
>
Vorname
</label></th>
<td><input
id=
"inputFirstname"
name=
"inputFirstname"
type=
"text"
placeholder=
"Vorname"
required
></td>
</tr>
<tr>
<th><label
for=
"lastname"
>
Nachname
</label></th>
<td><input
id=
"inputLastname"
name=
"inputLastname"
type=
"text"
placeholder=
"Nachname"
required
></td>
</tr>
<tr>
<th><label
for=
"email"
>
Email
</label></th>
<td><input
id=
"inputEmail"
name=
"inputEmail"
type=
"text"
placeholder=
"Email"
required
></td>
</tr>
<tr>
<th><label
for=
"organisation"
>
Unternehmen
</label></th>
<td><input
id=
"inputOrganisation"
name=
"inputOrganisation"
type=
"text"
placeholder=
"Unternehmen"
></td>
</tr>
<tr>
<th><label
for=
"industry"
>
Branche
</label></th>
<td><input
id=
"inputIndustry"
name=
"inputIndustry"
type=
"text"
placeholder=
"Branche"
></td>
</tr>
<tr>
<th><label
for=
"speciality"
>
Fachgebiete
</label></th>
<td><input
id=
"inputSpeciality"
name=
"inputSpeciality"
type=
"text"
placeholder=
"Fachgebiete"
></td>