Compare commits
4 Commits
d48aca05bc
...
ba8be413b7
Author | SHA1 | Date |
---|---|---|
|
ba8be413b7 | 2 years ago |
|
54f5a173ef | 2 years ago |
|
b4a0bd1be7 | 2 years ago |
|
7f92f3e721 | 2 years ago |
13 changed files with 616 additions and 273 deletions
@ -0,0 +1,13 @@ |
|||
module.exports = { |
|||
path: "/authenticate", |
|||
/** |
|||
* apps verify token |
|||
* @url /api/authenticate |
|||
* @method POST |
|||
* @POST ['applicationId', 'applicationSecret', 'userId', 'token'] |
|||
* @TODO add implementation |
|||
*/ |
|||
post: async (req, res) => { |
|||
return res.end(); |
|||
} |
|||
}; |
@ -0,0 +1,26 @@ |
|||
module.exports = { |
|||
path: "/cancel", |
|||
/** |
|||
* cancel app request and clear it |
|||
* @url /api/cancel |
|||
* @method GET |
|||
*/ |
|||
get: (req, res) => { |
|||
// if user is logged in
|
|||
if(req.session && req.session.user) { |
|||
req.session.appRequest = {}; |
|||
|
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 200, |
|||
message: 'msg.request.operation.cancel.successful' |
|||
})); |
|||
|
|||
// user isnt logged in
|
|||
} else { |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.login.required' |
|||
})); |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,78 @@ |
|||
var sanitize = require('mongo-sanitize'); |
|||
let db = global['requireModule']('database'); |
|||
|
|||
module.exports = { |
|||
path: "/login", |
|||
/** |
|||
* login a user |
|||
* @url /api/login |
|||
* @method POST |
|||
* @POST ['email', 'password'] |
|||
* @TODO add new activity 'action.user.login' |
|||
*/ |
|||
post: async (req, res) => { |
|||
// if user is logged in (existing session); FAIL
|
|||
if(req.session.user) { |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.logout.required' |
|||
})); |
|||
} |
|||
|
|||
// check body variables
|
|||
if(!req.body.email || !req.body.password) { |
|||
return res.type('json').status(401).end(JSON.stringify({ |
|||
status: 401, |
|||
message: [ |
|||
'msg.request.data.missing', |
|||
'msg.auth.login.failed' |
|||
] |
|||
})); |
|||
} |
|||
let email = sanitize(req.body.email); |
|||
let pass = sanitize(req.body.password); |
|||
|
|||
// database query: get user by email
|
|||
user = await db.getUser(email); |
|||
|
|||
// if database error
|
|||
if(user.err) { |
|||
// log error while debugging
|
|||
global['logs'].debug(user.err); |
|||
|
|||
// login failed because of database error
|
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: [ |
|||
'msg.database.error', |
|||
'msg.auth.login.failed' |
|||
] |
|||
})); |
|||
} |
|||
|
|||
// no reply (user does not exist) or password is wrong
|
|||
if(!user.reply || user.reply === null || user.reply.length == 0 || user.reply.length > 1 || !global['requireModule']('auth').validateHash(user.reply.passhash, pass)) { |
|||
return res.type('json').status(401).end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.login.failed' |
|||
})); |
|||
// do login
|
|||
} else { |
|||
// add cookies; login
|
|||
// new activity 'action.user.login'
|
|||
|
|||
// add session data
|
|||
req.session.user = { |
|||
'id': user.reply._id, |
|||
'group': user.reply.group |
|||
}; |
|||
|
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 200, |
|||
message: 'msg.auth.login.successful', |
|||
type: 'form' // TODO: types - { form, access_app}
|
|||
})); |
|||
} |
|||
|
|||
} |
|||
}; |
@ -0,0 +1,25 @@ |
|||
module.exports = { |
|||
path: "/logout", |
|||
/** |
|||
* logout user |
|||
* @url /api/logout |
|||
* @method GET |
|||
*/ |
|||
get: (req, res) => { |
|||
// user needs to be logged in
|
|||
if(!req.session || !req.session.user) { |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.login.required' |
|||
})); |
|||
// logout user
|
|||
} else { |
|||
res.clearCookie('RememberMe'); |
|||
req.session.destroy(); |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 200, |
|||
message: 'msg.auth.logout.successful' |
|||
})); |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,78 @@ |
|||
let db = global['requireModule']('database'); |
|||
|
|||
module.exports = { |
|||
path: "/redirect", |
|||
/** |
|||
* redirect user to app |
|||
* @url /api/redirect |
|||
* @method GET |
|||
* @GET ['id'] |
|||
*/ |
|||
get: async (req, res) => { |
|||
// if user is logged in
|
|||
if(req.session && req.session.user) { |
|||
// missing query data to retrieve app
|
|||
if(!req.query || !req.query.id) { |
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: [ |
|||
'msg.request.data.missing' |
|||
] |
|||
})); |
|||
} |
|||
|
|||
// set auth code
|
|||
authCode = await db.setAuthCode({ |
|||
aId: req.query.id, |
|||
uId: req.session.user.id |
|||
}); |
|||
|
|||
// database error
|
|||
if(typeof authCode.err !== "undefined") { |
|||
global['logs'].debug(authCode.err); |
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: [ |
|||
'msg.database.error' |
|||
] |
|||
})); |
|||
} |
|||
else if(typeof authCode.reply !== "undefined") { |
|||
// retrieve apps
|
|||
apps = await db.getApps(); |
|||
// database error
|
|||
if(typeof apps.err !== "undefined") { |
|||
global['logs'].debug(apps.err); |
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: [ |
|||
'msg.database.error' |
|||
] |
|||
})); |
|||
} |
|||
// for each app
|
|||
apps.reply.forEach((app) => { |
|||
// if app.id is equal to queried app
|
|||
if(app.id == req.query.id) { |
|||
// redirect to app
|
|||
return res.redirect(app.access+"?uid="+req.session.user.id+"&token="+authCode.reply.token); |
|||
} |
|||
}); |
|||
} else { |
|||
// database error
|
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: [ |
|||
'msg.database.error' |
|||
] |
|||
})); |
|||
} |
|||
// user isnt logged in
|
|||
} else { |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.login.required' |
|||
})); |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,17 @@ |
|||
module.exports = { |
|||
path: "/register", |
|||
/** |
|||
* register a user; currently not implemented |
|||
* @url /register |
|||
* @method POST |
|||
*/ |
|||
post: async (req, res) => { |
|||
// if registration is disabled
|
|||
if(!global['gds'].cfg.web.registration) { |
|||
return res.type('json').status(400).end(JSON.stringify({status: 400, message: "msg.auth.registration.deactivated"})); |
|||
} else { |
|||
// am i rite?
|
|||
return res.type('json').status(200).end(JSON.stringify({})); |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,95 @@ |
|||
let sanitize = require('mongo-sanitize'); |
|||
let db = global['requireModule']('database'); |
|||
let crypto = require('crypto'); |
|||
let auth = global['requireModule']('auth'); |
|||
|
|||
module.exports = { |
|||
path: "/settings", |
|||
/** |
|||
* update user |
|||
* @TODO add implementation |
|||
* @url /api/settings |
|||
* @method POST |
|||
* @POST ['email', 'password', 'repassword', 'mfa'] |
|||
*/ |
|||
post: async (req, res) => { |
|||
// if user is not logged in; FAIL
|
|||
if(!req.session || !req.session.user) { |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.logout.required' |
|||
})); |
|||
} |
|||
|
|||
// check body variables
|
|||
if( |
|||
!( |
|||
(req.body.email) || |
|||
(req.body.password && req.body.repassword) || |
|||
(req.body.mfa) |
|||
) |
|||
) { |
|||
return res.type('json').status(401).end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.request.data.missing' |
|||
})); |
|||
} |
|||
|
|||
user = await db.getUser(req.session.user.id); |
|||
// if database error
|
|||
if(user.err) { |
|||
// log error while debugging
|
|||
global['logs'].debug(user.err); |
|||
|
|||
// query failed because of database error
|
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: 'msg.database.error' |
|||
})); |
|||
} |
|||
|
|||
obj = {}; |
|||
if(req.body.email) obj.email = sanitize(req.body.email); |
|||
if(req.body.password && req.body.repassword) { |
|||
password = sanitize(req.body.password); |
|||
repassword = sanitize(req.body.repassword); |
|||
if(password.length == repassword.length && crypto.timingSafeEqual( |
|||
Buffer.from(password, 'hex'), |
|||
Buffer.from(repassword, 'hex') |
|||
)) { |
|||
obj.passhash = auth.generateHash(password); |
|||
} else { |
|||
return res.type('json').status(400).end(JSON.stringify({status: 400, message: "msg.request.data.missing"})); |
|||
} |
|||
} |
|||
|
|||
// empty obj, do not update
|
|||
if(Object.keys(obj).length === 0 && obj.constructor === Object) { |
|||
return res.type('json').status(400).end(JSON.stringify({status: 400, message: "msg.request.data.missing"})); |
|||
} |
|||
update = await db.updateUser(user.reply._id, obj); |
|||
// if database error
|
|||
if(update.err) { |
|||
// log error while debugging
|
|||
global['logs'].debug(update.err); |
|||
|
|||
// update failed because of database error
|
|||
return res.type('json').status(500).end(JSON.stringify({ |
|||
status: 500, |
|||
message: 'msg.database.error' |
|||
})); |
|||
} |
|||
else if(update.reply) { |
|||
console.log(obj); |
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 200, |
|||
message: 'msg.settings.update.successful' |
|||
})); |
|||
} |
|||
|
|||
return res.type('json').end(JSON.stringify({ |
|||
status: 401, |
|||
message: 'msg.auth.logout.required' |
|||
})); |
|||
} |
|||
}; |
@ -1,23 +1,17 @@ |
|||
extends blocks/layout.pug |
|||
append var |
|||
if(session && !session.user) |
|||
- var breadcrumb = {0: {"name": cfg.app.name, "href": "/"}, 1: {"name": "Forgot your password?", "active": true}}; |
|||
- var title = "Reset password"; |
|||
- var breadcrumb = {0: {"name": cfg.app.name, "href": "/"}, 1: {"name": "Forgot your password?", "active": true}}; |
|||
- var title = "Reset password"; |
|||
|
|||
append content |
|||
if(session && !session.user) |
|||
.uk-flex.uk-margin-medium-top.uk-margin-medium-bottom |
|||
div(class="uk-width-auto [email protected]") |
|||
.uk-flex.uk-flex-auto.uk-flex-column.uk-flex-center.uk-margin-left.uk-margin-right |
|||
h1 Reset Password |
|||
form.uk-form-horizontal |
|||
.uk-margin |
|||
label.uk-form-label(for="login_user") Username / Email |
|||
.uk-form-controls |
|||
input.uk-input#login_user(type="text", placeholder="tetrahedron") |
|||
a(href="#").uk-button.uk-button-default Reset password |
|||
div(class="uk-width-auto [email protected]") |
|||
else |
|||
append var |
|||
- overwrite_vars = (session && session.user) ? true : false; |
|||
include blocks/error/permission.pug |
|||
.uk-flex.uk-margin-medium-top.uk-margin-medium-bottom |
|||
div(class="uk-width-auto [email protected]") |
|||
.uk-flex.uk-flex-auto.uk-flex-column.uk-flex-center.uk-margin-left.uk-margin-right |
|||
h1 Reset Password |
|||
form.uk-form-horizontal |
|||
.uk-margin |
|||
label.uk-form-label(for="login_user") Username / Email |
|||
.uk-form-controls |
|||
input.uk-input#login_user(type="text", placeholder="tetrahedron") |
|||
a(href="#").uk-button.uk-button-default Reset password |
|||
div(class="uk-width-auto [email protected]") |
|||
|
@ -0,0 +1,93 @@ |
|||
extends blocks/layout.pug |
|||
append var |
|||
if(session && session.user) |
|||
- var breadcrumb = {0: {"name": cfg.app.name, "href": "/"}, 1: {"name": "Settings", "active": true}}; |
|||
- var title = "Settings"; |
|||
|
|||
mixin setting(name, id, inputId, hidden, inputType, inputValue, inputPlaceholder, inputIcon, inputDisabled) |
|||
.uk-margin(id=id) |
|||
label.uk-form-label(for=inputId)=name |
|||
if(inputIcon) |
|||
.uk-inline.uk-width-1-1 |
|||
span.uk-form-icon(uk-icon="icon: "+inputIcon) |
|||
if(inputDisabled == "disabled") |
|||
input.uk-input(id=inputId, type=inputType, value=inputValue, placeholder=inputPlaceholder, disabled) |
|||
else |
|||
input.uk-input(id=inputId, type=inputType, value=inputValue, placeholder=inputPlaceholder) |
|||
else |
|||
input.uk-input(id=inputId, type=inputType, value=inputValue, placeholder=inputPlaceholder) |
|||
//-.uk-card.uk-card-default |
|||
.uk-card-header.uk-card-primary |
|||
h3.uk-card-title=name |
|||
.uk-card-body |
|||
p=id |
|||
.uk-card-footer.uk-flex.uk-flex-right |
|||
a.uk-button.uk-button-default.uk-button-primary(href="/api/redirect?id="+id) Login |
|||
|
|||
mixin settings() |
|||
form(class="uk-child-width-expand uk-margin-bottom", uk-grid) |
|||
fieldset.uk-fieldset |
|||
h1 Settings |
|||
|
|||
h2 Profile |
|||
+setting('', 'lorem-ipsum', 'form-profile-username', 'false', 'text', user.nickname, '', 'user', 'disabled') |
|||
+setting('', 'lorem-ipsum', 'form-profile-email', 'false', 'text', user.email, '[email protected]', 'mail') |
|||
div(class="uk-flex uk-flex-between uk-margin-bottom", uk-grid) |
|||
div(class="[email protected]") |
|||
#profile_msg.uk-alert(data-uk-alert).uk-hidden |
|||
a.uk-close-alt.uk-alert-close(href="#") |
|||
p |
|||
div |
|||
a(onclick="saveProfile(event)").uk-button.uk-button-primary Save |
|||
|
|||
h2 Password |
|||
+setting('Password', 'form-password', 'form-security-password', 'false', 'password', '', '') |
|||
+setting('Reenter Password', 'form-repassword', 'form-security-repassword', 'false', 'password', '', '') |
|||
div(class="uk-flex uk-flex-between uk-margin-bottom", uk-grid) |
|||
div(class="[email protected]") |
|||
#password_msg.uk-alert(data-uk-alert).uk-hidden |
|||
a.uk-close-alt.uk-alert-close(href="#") |
|||
p |
|||
div |
|||
a(onclick="savePassword(event)").uk-button.uk-button-primary Save |
|||
|
|||
|
|||
div(class="uk-flex uk-flex-between uk-margin-bottom", uk-grid) |
|||
div(class="[email protected] uk-flex-column") |
|||
h2 Multifactor Authentication |
|||
#mfa_msg.uk-alert(data-uk-alert).uk-hidden |
|||
a.uk-close-alt.uk-alert-close(href="#") |
|||
p |
|||
div |
|||
if(user.mfa && user.mfa.active) |
|||
a(onclick="switchMFA(event)").uk-button.uk-button-primary Disable |
|||
if(!user.mfa || !user.mfa.active) |
|||
a(onclick="switchMFA(event)").uk-button.uk-button-primary Enable |
|||
if(user.mfa && user.mfa.active) |
|||
div(class="uk-flex uk-flex-between uk-margin-bottom", uk-grid) |
|||
div(class="uk-width-1-1") |
|||
if(user.mfa.data) |
|||
//- sort by number |
|||
- user.mfa.data.sort(function(a, b) {return a.no - b.no; }) |
|||
each option in user.mfa.data |
|||
.uk-card.uk-card-default.uk-card-body.uk-margin-bottom.uk-width-1-1 |
|||
.uk-flex.uk-flex-between |
|||
div |
|||
h3.uk-card-title= "Authentication Layer: "+option.no |
|||
div |
|||
p= "type: " |
|||
span.uk-badge= option.type |
|||
.uk-flex.uk-flex-between |
|||
div |
|||
a.uk-button.uk-button-default(onclick="showMFASecret(event)", id="secret.show."+option.type+"."+option.no) Show/Hide Secret |
|||
div |
|||
a.uk-button.uk-button-primary(onclick="removeMFA(event)", id="secret.remove."+option.type+"."+option.no) remove Layer |
|||
p(class="secret uk-hidden", id="secret."+option.type+"."+option.no, data-secret=option.data)= "SECRET: " + option.data |
|||
|
|||
|
|||
append content |
|||
if(session && session.user) |
|||
.uk-container |
|||
+settings() |
|||
else |
|||
include blocks/login.pug |
Loading…
Reference in new issue