-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
41 changed files
with
5,503 additions
and
2,927 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,4 +10,5 @@ vocascan.config.* | |
!docker/**/vocascan.config.* | ||
docker/**/database | ||
*.log | ||
/staticPages | ||
*.log.gz | ||
/staticPages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
const httpStatus = require('http-status'); | ||
const config = require('../config/config/index.js'); | ||
const ApiError = require('../utils/ApiError.js'); | ||
const catchAsync = require('../utils/catchAsync.js'); | ||
const { verifyJWT, hashEmail } = require('../utils/index.js'); | ||
const { verifyUser, sendAccountVerificationEmail } = require('../Services/AuthServiceProvider.js'); | ||
const { tokenTypes } = require('../utils/constants.js'); | ||
const logger = require('../config/logger'); | ||
|
||
const requestEmailVerification = catchAsync(async (req, res) => { | ||
if (!config.service.email_confirm) { | ||
throw new ApiError(httpStatus.NOT_FOUND); | ||
} | ||
|
||
if (req.user.emailVerified) { | ||
throw new ApiError(httpStatus.GONE, 'User is already verified'); | ||
} | ||
|
||
if (hashEmail(req.body.email) !== req.user.email) { | ||
throw new ApiError(httpStatus.BAD_REQUEST, 'Email not valid', 'email'); | ||
} | ||
|
||
await sendAccountVerificationEmail({ ...req.user.toJSON(), email: req.body.email }); | ||
|
||
res.status(httpStatus.NO_CONTENT).end(); | ||
}); | ||
|
||
const verifyEmail = catchAsync(async (req, res) => { | ||
const { token } = req.query; | ||
|
||
if (!token) { | ||
return res.render('accountVerification', { | ||
status: httpStatus.BAD_REQUEST, | ||
error: 'No verification token provided', | ||
}); | ||
} | ||
|
||
let payload = ''; | ||
|
||
try { | ||
payload = await verifyJWT(token, config.server.jwt_secret); | ||
|
||
if (payload.type !== tokenTypes.VERIFY_EMAIL) { | ||
throw new Error(); | ||
} | ||
} catch (error) { | ||
return res.render('accountVerification', { | ||
status: httpStatus.UNAUTHORIZED, | ||
error: 'No valid verification token provided', | ||
}); | ||
} | ||
|
||
let user = null; | ||
|
||
try { | ||
user = await verifyUser({ id: payload.id }); | ||
} catch (error) { | ||
if (error instanceof ApiError) { | ||
return res.render('accountVerification', { | ||
status: httpStatus.GONE, | ||
error: 'User is already verified', | ||
}); | ||
} | ||
|
||
logger.error(error); | ||
|
||
return res.render('accountVerification', { | ||
status: httpStatus.INTERNAL_SERVER_ERROR, | ||
error: 'Internal Server Error', | ||
}); | ||
} | ||
|
||
return res.render('accountVerification', { | ||
status: httpStatus.OK, | ||
error: null, | ||
user, | ||
}); | ||
}); | ||
|
||
module.exports = { | ||
requestEmailVerification, | ||
verifyEmail, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,64 @@ | ||
const { parseTokenUserId } = require('../utils'); | ||
const { verifyJWT } = require('../utils'); | ||
const { User } = require('../../database'); | ||
const ApiError = require('../utils/ApiError.js'); | ||
const httpStatus = require('http-status'); | ||
const catchAsync = require('../utils/catchAsync'); | ||
const config = require('../config/config'); | ||
const { tokenTypes } = require('../utils/constants'); | ||
|
||
// Check for Authorization header and add user attribute to request object | ||
const ProtectMiddleware = catchAsync(async (req, _res, next) => { | ||
// Break if no Authorization header is set | ||
if (!req.header('Authorization')) { | ||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Not Authorized'); | ||
} | ||
|
||
let userId; | ||
|
||
try { | ||
// Read userId from token | ||
userId = await parseTokenUserId(req, config.server.jwt_secret); | ||
} catch (err) { | ||
// Handle broken token | ||
throw new ApiError(httpStatus.BAD_REQUEST, 'Invalid auth token'); | ||
} | ||
|
||
// Get user from database | ||
const user = await User.findOne({ | ||
where: { | ||
id: userId, | ||
}, | ||
}); | ||
const ProtectMiddleware = (emailVerified = true) => | ||
catchAsync(async (req, _res, next) => { | ||
// Break if no Authorization header is set | ||
if (!req.header('Authorization')) { | ||
throw new ApiError(httpStatus.UNAUTHORIZED, 'Not Authorized'); | ||
} | ||
|
||
let payload = null; | ||
|
||
try { | ||
// Read userId from token | ||
const token = req.header('Authorization').split(' ')[1]; | ||
payload = await verifyJWT(token, config.server.jwt_secret); | ||
|
||
if (payload.type !== tokenTypes.ACCESS) { | ||
throw new Error(); | ||
} | ||
} catch (err) { | ||
// Handle broken token | ||
throw new ApiError(httpStatus.BAD_REQUEST, 'Invalid auth token'); | ||
} | ||
|
||
if (!user) { | ||
throw new ApiError(httpStatus.BAD_REQUEST, 'Invalid auth token'); | ||
} | ||
// Get user from database | ||
const user = await User.findOne({ | ||
where: { | ||
id: payload.id, | ||
}, | ||
}); | ||
|
||
// Inject user into request object | ||
req.user = user; | ||
if (!user || user.disabled) { | ||
throw new ApiError(httpStatus.BAD_REQUEST, 'Invalid auth token'); | ||
} | ||
|
||
next(); | ||
}); | ||
// Inject user into request object | ||
req.user = user; | ||
|
||
// check verification level | ||
if (emailVerified && !req.user.emailVerified) { | ||
// allow operations in time range | ||
if (config.service.email_confirm_level === 'medium') { | ||
if (new Date() - req.user.createdAt > config.service.email_confirm_time) { | ||
throw new ApiError(httpStatus.FORBIDDEN, 'Email not verified'); | ||
} | ||
} | ||
|
||
// dont allow any operations | ||
else if (config.service.email_confirm_level === 'high') { | ||
throw new ApiError(httpStatus.FORBIDDEN, 'Email not verified'); | ||
} | ||
} | ||
|
||
next(); | ||
}); | ||
|
||
module.exports = ProtectMiddleware; |
Oops, something went wrong.