Fix most glaring bugs and vulnerabilities

This commit is contained in:
Luka Romih
2023-05-08 23:25:25 +02:00
parent 9867875ef2
commit d0e53fee3b
144 changed files with 2231 additions and 2981 deletions
+9 -9
View File
@@ -6,18 +6,18 @@ const portal = require('../controllers/portals')
// All routes require an authenticated user.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
res.redirect('/')
res.redirect(303, '/')
})
// Menu entry point. Redirect based on role.
router.get('/', (req, res, next) => {
const { user, baseUrl } = req
if (user.hasRole('portal admin')) {
return res.redirect(`${baseUrl}/nastavitve/portal`)
return res.redirect(303, `${baseUrl}/nastavitve/portal`)
} else if (user.hasRole('dictionaries admin')) {
return res.redirect(`${baseUrl}/slovarji`)
return res.redirect(303, `${baseUrl}/slovarji`)
}
res.redirect('/')
res.redirect(303, '/')
})
// Authorize endpoints for portal admin.
@@ -25,14 +25,14 @@ router.use(
['/nastavitve', '/povezave', '/uporabniki', '/komentarji'],
(req, res, next) => {
if (req.user.hasRole('portal admin')) return next()
res.redirect('/')
res.redirect(303, '/')
}
)
// Authorize endpoints for dictionaries admin.
router.use(['/slovarji', '/podrocja'], (req, res, next) => {
router.use(['/slovarji', '/podpodrocja'], (req, res, next) => {
if (req.user.hasRole('dictionaries admin')) return next()
res.redirect('/')
res.redirect(303, '/')
})
router.get('/nastavitve/portal', portal.instanceSettings)
@@ -59,9 +59,9 @@ router.get('/povezave/seznam/:portalId', portal.fetchSelectedLinkedDictionaries)
router.post('/povezave/seznam/:portalId', portal.updateSelectedDictionaries)
router.get('/povezava/:portalId/urejanje', portal.fetchPortal)
router.get('/povezave/:portalId/urejanje', portal.fetchPortal)
router.post('/povezava/:portalId/urejanje', portal.updatePortal)
router.post('/povezave/:portalId/urejanje', portal.updatePortal)
// Show a list of user's dictionaries.
router.get('/slovarji', dictionary.listAdminDictionaries)
-8
View File
@@ -3,20 +3,12 @@ const router = require('express-promise-router')()
const {
listComments,
createComment,
seedComments,
clearComments,
updateStatus
} = require('../../../controllers/api/v1/comments')
// List comments (one page).
router.get('/', listComments)
// TEMP - Seed comments.
router.get('/seed/:commentCount', seedComments)
// TEMP - Clear comments.
router.get('/clear', clearComments)
// All further routes are only available to authenticated users.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
-6
View File
@@ -2,8 +2,6 @@ const router = require('express-promise-router')()
const {
assign,
listEntries,
listNewEntries,
createQuestion,
deleteQuestion,
updateDomain,
@@ -23,10 +21,6 @@ const {
router.get('/entry-pagination', sendPaginationData)
router.get('/entry', listEntries)
router.get('/new-entry', listNewEntries)
// All routes require an authenticated user.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
-7
View File
@@ -1,7 +0,0 @@
const router = require('express-promise-router')()
const demoPaginacija = require('../../../controllers/api/v1/demo-paginacija')
// Tale endpoint vrača rezultate.
router.get('/list', demoPaginacija.list)
module.exports = router
+50 -13
View File
@@ -1,54 +1,91 @@
const router = require('express-promise-router')()
const dictionaries = require('../../../controllers/api/v1/dictionaries')
const user = require('../../../middleware/user')
// Update domain labels.
router.post('/update-domain-labels', dictionaries.updateDomainLabels)
// Update secondary domains
router.post('/renovateSecondaryDomains', dictionaries.renovateSecondaryDomains)
router.post(
'/renovateSecondaryDomains',
user.canAdministrateDictionaries,
dictionaries.renovateSecondaryDomains
)
// Delete specific dictionary.
router.delete('/:dictionaryId', dictionaries.delete)
router.delete(
'/:dictionaryId',
user.canAdministrateDictionary,
dictionaries.delete
)
// Change page in pagination
router.get('/listAllDictionaries', dictionaries.listDictionaries)
router.get(
'/listAllDictionaries',
user.canAdministrateDictionaries,
dictionaries.listDictionaries
)
// Change page in pagination
router.get('/:dictionaryId/listDomainLabels', dictionaries.listDomainLabels)
// Change page in pagination
router.get('/listSecondaryDomains', dictionaries.listSecondaryDomains)
router.get(
'/:dictionaryId/listDomainLabels',
user.canAdministrateDictionary,
dictionaries.listDomainLabels
)
// Change page in pagination
router.get(
'/:dictionaryId/showImportFromFileForm',
user.canContentEdit,
dictionaries.showImportFromFileForm
)
// Change page in pagination
router.get(
'/:dictionaryId/showExportToFileForm',
user.canContentEdit,
dictionaries.showExportToFileForm
)
// Delete all entries of specific dictionary.
router.delete('/:dictionaryId/entries/all', dictionaries.deleteAllEntries)
router.delete(
'/:dictionaryId/entries/all',
user.canAdministrateDictionary,
dictionaries.deleteAllEntries
)
// Publish all entries of specific dictionary.
router.put('/:dictionaryId/entries/all/publish', dictionaries.publishAllEntries)
router.put(
'/:dictionaryId/entries/all/publish',
user.canAdministrateDictionary,
dictionaries.publishAllEntries
)
// Import term candidates from extraction.
router.post(
'/:id/import-extraction/:extractionId',
'/:dictionaryId/import-extraction/:extractionId',
user.canContentEdit,
dictionaries.importFromExtraction
)
// Export dictionary into a file.
router.post('/:id/export-begin', dictionaries.exportBegin)
router.post(
'/:dictionaryId/export-begin',
user.canContentEdit,
dictionaries.exportBegin
)
router.get('/:dictionaryId/domainLabels', dictionaries.listFilteredDomainLabels)
router.get(
'/:dictionaryId/domainLabels',
user.canContentEdit,
dictionaries.listFilteredDomainLabels
)
router.get('/secondaryDomains', dictionaries.listSecondaryDomainData)
router.get(
'/secondaryDomains',
user.canAdministrateDictionaries,
dictionaries.listSecondaryDomainData
)
module.exports = router
+3 -1
View File
@@ -1,5 +1,6 @@
// This page refers to dictionary entries, not consultancy or other entries
const router = require('express-promise-router')()
const user = require('../../../middleware/user')
const {
getEntry,
@@ -10,7 +11,8 @@ const {
getEntryVersionSnapshot
} = require('../../../controllers/api/v1/dictionaries')
// TODO Add authorization.
// All further routes are only available to authenticated users with dictionary content editing rights.
router.use(user.isAuthenticated, user.canContentEdit)
// Render entry data for the selected entry
router.get('/', getEntry)
+42 -20
View File
@@ -1,54 +1,76 @@
const router = require('express-promise-router')()
const extraction = require('../../../controllers/api/v1/extraction')
const { validateOwnership } = require('../../../controllers/extraction')
// TODO In final version test authentication and authorization.
// TODO Also try to lock file editing or other operations once extraction was started.
// TODO Try to lock file editing or other operations once extraction was started.
// All further routes are only available to authenticated users.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
res.status(400).end()
})
// Delete extraction.
router.delete('/:id', extraction.delete)
router.delete('/:id', validateOwnership, extraction.delete)
// List documents.
router.get('/:id/documents', extraction.docsList)
router.get('/:id/documents', validateOwnership, extraction.docsList)
// Update documents.
router.put('/:id/documents', extraction.docsUpdate)
router.put('/:id/documents', validateOwnership, extraction.docsUpdate)
// Delete a specific document.
router.delete('/:id/documents/:filename', extraction.docDelete)
router.delete(
'/:id/documents/:filename',
validateOwnership,
extraction.docDelete
)
// List stop term files.
router.get('/:id/stop-terms', extraction.stopTermsList)
router.get('/:id/stop-terms', validateOwnership, extraction.stopTermsList)
// Update stop term files.
router.put('/:id/stop-terms', extraction.stopTermsUpdate)
router.put('/:id/stop-terms', validateOwnership, extraction.stopTermsUpdate)
// Delete a specific stop term file.
router.delete('/:id/stop-terms/:filename', extraction.stopTermDelete)
router.delete(
'/:id/stop-terms/:filename',
validateOwnership,
extraction.stopTermDelete
)
// Save oss params.
router.post('/:id/oss-save-params', extraction.ossSaveParams)
router.post('/:id/oss-save-params', validateOwnership, extraction.ossSaveParams)
// Execute search by oss params.
router.put('/:id/oss-search', extraction.ossSearch)
router.put('/:id/oss-search', validateOwnership, extraction.ossSearch)
// Confirm oss params.
router.put('/:id/oss-confirm-params', extraction.ossConfirmParams)
router.put(
'/:id/oss-confirm-params',
validateOwnership,
extraction.ossConfirmParams
)
// Begin extraction.
router.put('/:id/begin', extraction.begin)
router.put('/:id/begin', validateOwnership, extraction.begin)
// Duplicate extraction.
router.post('/:id/duplicate', extraction.duplicate)
router.post('/:id/duplicate', validateOwnership, extraction.duplicate)
// Export term candidates.
router.get('/:id/term-candidates-export', extraction.termCandidatesExport)
// List all finished extractions for current user.
// TODO Is this enpoint even necessarry?
router.get('/finished-for-user', extraction.listFinishedForUser)
router.get(
'/:id/term-candidates-export',
validateOwnership,
extraction.termCandidatesExport
)
// List term candidates for specific extraction.
router.get('/:id/term-candidates', extraction.listTermCandidates)
router.get(
'/:id/term-candidates',
validateOwnership,
extraction.listTermCandidates
)
module.exports = router
-2
View File
@@ -7,7 +7,6 @@ const dictionariesRouter = require('./dictionaries')
const portalsRouter = require('./portals')
const searchRouter = require('./search')
const consultancyRouter = require('./consultancy')
const demoPaginacijaRouter = require('./demo-paginacija')
const extractionRouter = require('./extraction')
router.use('/comments', commentsRouter)
@@ -18,7 +17,6 @@ router.use('/dictionaries', dictionariesRouter)
router.use('/portals', portalsRouter)
router.use('/search', searchRouter)
router.use('/consultancy', consultancyRouter)
router.use('/demo-paginacija', demoPaginacijaRouter)
router.use('/extraction', extractionRouter)
module.exports = router
+4
View File
@@ -1,4 +1,5 @@
const router = require('express-promise-router')()
const user = require('../../../middleware/user')
const {
create,
@@ -10,6 +11,9 @@ const {
deleteLinkedDictionary
} = require('../../../controllers/api/v1/portals')
// All further routes are only available to portal admin.
router.use(user.isAuthenticated, user.isPortalAdmin)
// Create new portal connection
router.post('/createPortal', create)
+2 -2
View File
@@ -5,11 +5,11 @@ const user = require('../../../middleware/user')
// Return search results for main search.
router.get('/main', search.listMainEntries)
// TODO This route assumes existance of user. Make sure to pre check it.
// Return search results for editor search.
router.get(
'/editor/:dictionaryId',
user.isDictionaryEditor,
user.isAuthenticated,
user.canContentEdit,
search.listEditorEntries
)
+7 -1
View File
@@ -4,12 +4,18 @@ const {
listDictionaries,
syncDictionary
} = require('../../../controllers/api/v1/inter_instance_sync')
const user = require('../../../middleware/user')
// Receive Content Security Policy violation reports.
router.post('/csp-reports', system.handleCspReports)
// Trigger synchronization with Eurotermbank.
router.get('/eurotermbank-sync-push', system.syncWithEurotermbank)
router.get(
'/eurotermbank-sync-push',
user.isAuthenticated,
user.isPortalAdmin,
system.syncWithEurotermbank
)
// List dictionaries (one page).
router.get('/inter-instance-sync/dictionaries', listDictionaries)
+30 -3
View File
@@ -1,6 +1,7 @@
const router = require('express-promise-router')()
const user = require('../../../controllers/users')
const users = require('../../../controllers/api/v1/users')
const userAuth = require('../../../middleware/user')
// Validate and create a new user.
router.post('/register', user.register)
@@ -8,12 +9,38 @@ router.post('/register', user.register)
// Validate and log the user in.
router.post('/login', user.login)
router.get('/addUser', user.findByUsernameOrEmail)
// Supply user with the token to set a new password.
router.post('/reset-password-init', user.generateResetPasswordToken)
router.get('/listAllUsers', users.listUsers)
// Validate new passwords, change if successful and sign the user in.
router.post('/reset-password-submit', user.changePassword)
// Find user by username or email in dictionary or admin console.
router.get(
'/addUser',
userAuth.isAuthenticated,
userAuth.canAdministrateDictionary,
user.findByUsernameOrEmail
)
// List all users in the admin console.
router.get(
'/listAllUsers',
userAuth.isAuthenticated,
userAuth.isPortalAdmin,
users.listUsers
)
// Update hits per page setting of the requesting user.
router.post('/hitsPerPage', users.updateHitsPerPage)
router.post('/nameAndSurname', users.updateFristNameAndSurname)
// Update first name, last name and email of the requesting user.
router.post('/basic-data', users.updateBasicData)
// Update password of the requesting user.
router.post('/password', users.updatePassword)
// Delete user profile of the requesting user.
router.delete('/current', users.deleteCurrent)
module.exports = router
+38 -9
View File
@@ -1,5 +1,6 @@
const router = require('express-promise-router')()
const user = require('../middleware/user')
const { consultancy, consultancyAdmin } = require('../controllers/consultancy')
router.get('/', consultancy.index)
@@ -12,23 +13,51 @@ router.get('/vprasanje/:id', consultancy.specificQuestion)
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
res.redirect('/')
res.redirect(303, '/')
})
router.get('/vprasanje/admin/novo', consultancyAdmin.new)
router.get(
'/vprasanje/admin/novo',
user.canAdministrateConsultancy,
consultancyAdmin.new
)
router.get('/vprasanje/admin/svetovalci', consultancyAdmin.users)
router.get(
'/vprasanje/admin/svetovalci',
user.canAdministrateConsultancy,
consultancyAdmin.users
)
router.get('/vprasanje/admin/zavrnjeno', consultancyAdmin.rejected)
router.get(
'/vprasanje/admin/zavrnjeno',
user.canAdministrateConsultancy,
consultancyAdmin.rejected
)
router.get('/vprasanje/admin/objavljeno', consultancyAdmin.published)
router.get(
'/vprasanje/admin/objavljeno',
user.canConsult,
consultancyAdmin.published
)
router.get('/vprasanje/admin/pripravljeno', consultancyAdmin.prepared)
router.get(
'/vprasanje/admin/pripravljeno',
user.canAdministrateConsultancy,
consultancyAdmin.prepared
)
router.get('/vprasanje/admin/v-delu', consultancyAdmin.inProgress)
router.get(
'/vprasanje/admin/v-delu',
user.canConsult,
consultancyAdmin.inProgress
)
router.get('/vprasanje/admin/statistika', consultancyAdmin.statistics)
// router.get('/vprasanje/admin/statistika', consultancyAdmin.statistics)
router.get('/vprasanje/admin/urejanje/:id', consultancyAdmin.edit)
router.get(
'/vprasanje/admin/urejanje/:id',
user.canConsultEntry,
consultancyAdmin.edit
)
module.exports = router
+1 -8
View File
@@ -13,7 +13,7 @@ router.get('/:dictionaryId/o-slovarju', dictionary.dictionaryDetails)
// All further routes are only available to authenticated users.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
res.redirect(req.baseUrl)
res.redirect(303, req.baseUrl)
})
// Show a form to create a new dictionary.
@@ -92,13 +92,6 @@ router.get(
dictionary.showContent
)
// Validate and update dictionary content entries.
// router.post(
// '/:dictionaryId/vsebina',
// user.isDictionaryEditor,
// dictionary.updateContent
// )
// Show a form to export a dictionary.
router.get(
'/:dictionaryId/izvoz',
-27
View File
@@ -1,27 +0,0 @@
const router = require('express-promise-router')()
const extraction = require('../controllers/extraction-poc')
// TODO In final version test authentication and authorization.
// List all extractions.
router.get('/', extraction.list)
// Create new extraction.
router.post('/', extraction.create)
// Edit extraction.
router.get('/:id', extraction.edit)
// Update extraction (own documents).
router.post('/:id', extraction.updateOwn)
// Edit documents.
router.get('/:id/besedila', extraction.docsEdit)
// Edit stop terms.
router.get('/:id/stop-termini', extraction.stopTermsEdit)
// List term candidates for extraction and display export interface.
router.get('/:id/kandidati', extraction.listTermCandidates)
module.exports = router
+14 -36
View File
@@ -1,6 +1,5 @@
const router = require('express-promise-router')()
const extraction = require('../controllers/extraction')
const extractionPocRouter = require('./extraction-poc')
// List all extractions.
router.get('/', extraction.list)
@@ -8,54 +7,33 @@ router.get('/', extraction.list)
// All further routes are only available to authenticated users.
router.use((req, res, next) => {
if (req.isAuthenticated()) return next()
res.redirect(req.baseUrl)
res.redirect(303, req.baseUrl)
})
// Create new extraction.
router.post('/', extraction.create)
router.use('/poc', extractionPocRouter)
// Edit extraction.
router.get('/:id', extraction.edit)
router.get('/:id', extraction.validateOwnership, extraction.edit)
// Update extraction (own documents).
router.post('/:id', extraction.updateOwn)
router.post('/:id', extraction.validateOwnership, extraction.updateOwn)
// Edit documents.
router.get('/:id/besedila', extraction.docsEdit)
router.get('/:id/besedila', extraction.validateOwnership, extraction.docsEdit)
// Edit stop terms.
router.get('/:id/stop-termini', extraction.stopTermsEdit)
router.get(
'/:id/stop-termini',
extraction.validateOwnership,
extraction.stopTermsEdit
)
// List term candidates for extraction and display export interface.
router.get('/:id/kandidati', extraction.listTermCandidates)
// // TODO: Ask Luka or Miro what to do with this page.
// router.get('/id_luscenja/kandidati', (req, res) => {
// res.render('pages/extraction/terms', {
// title: 'Terminološki kandidati'
// })
// })
// // Show a form to export a dictionary
// router.get('/id_luscenja/dokumenti/besedila', (req, res) => {
// res.render('pages/extraction/docs-edit', {
// title: 'Besedila'
// })
// })
// // Show a form to export a dictionary
// router.get('/id_luscenja/oss', (req, res) => {
// res.render('pages/extraction/edit-oss', {
// title: 'KAS + dokumenti'
// })
// })
// router.get('/id_luscenja/dokumenti/termini', (req, res) => {
// res.render('pages/extraction/stop-terms-edit', {
// title: 'Termini'
// })
// })
router.get(
'/:id/kandidati',
extraction.validateOwnership,
extraction.listTermCandidates
)
module.exports = router
+11 -64
View File
@@ -1,11 +1,7 @@
const router = require('express-promise-router')()
const { isAuthenticated: isUserAuthenticated } = require('../middleware/user')
const db = require('../models/db')
const cache = require('../models/cache')
const { searchEngineClient } = require('../models/search-engine')
const index = require('../controllers/index')
const user = require('../controllers/users')
const demoPaginacija = require('../controllers/demo-paginacija')
// TODO Some of these endpoints might need authorization protection. Review and clean up at a later point.
@@ -18,54 +14,6 @@ router.get('/iskanje', index.search)
// Show a list of search results.
router.get('/termin/:entryId', index.entryDetails)
/*
router.get('/termin/id_termina', (req, res) => {
res.render('pages/search/result-detail')
})
*/
router.get('/keys', (req, res) => {
res.render('pages/search/special-keys-demo-rm-this')
})
router.get('/demo', (req, res) => {
res.render('pages/admin')
})
router.get('/select', (req, res) => {
res.render('pages/search-root')
})
router.get('/dictionaries', (req, res) => {
res.render('pages/my-dictionaries-root')
})
router.get('/db-query-demo', async (req, res) => {
const queryResult = await db.query("SELECT 'yes' as does_it_work")
res.send(queryResult.rows[0])
})
router.get('/test-seje', (req, res) => {
// req.session.before = { a: 1, b: 'yes' }
const { sessionID, session } = req
// req.session.after = { c: 2, d: 'no' }
res.send({ sessionID, session })
})
router.get('/test-cacha', async (req, res, next) => {
const sRes = await cache.set('my key', 'also my val')
const gRes = await cache.get('my key')
res.send({ sRes, gRes })
})
router.get('/test-iskalnika', async (req, res) => {
const response = await searchEngineClient.ping()
res.send(response)
})
// Stran z demo implementacijo paginirane vsebine.
router.get('/demo-paginacija', demoPaginacija.izrišiStran)
// Render help page
router.get('/pomoc', (req, res) => {
res.render('pages/help', { title: req.t('Pomoč') })
@@ -86,17 +34,9 @@ router.get('/slovarji/xml-schema', (req, res) => {
res.download('public/documents/dictionary_schema.xsd')
})
// Render demo help pug page.
router.get('/pomoc-pug-demo', (req, res) => {
res.render('pages/help-pug-demo-frame', { title: 'Pomoč - pug demo' })
})
// Activate user account.
router.get('/users/activate', user.activateAccount)
// Log the user out.
router.post('/users/logout', user.logout)
// Render privacy policy page
router.get('/politika-zasebnosti', (req, res) => {
res.render(`pages/privacy-policy_${req.language}`, {
@@ -111,6 +51,15 @@ router.get('/pogoji-uporabe', (req, res) => {
})
})
// Form for user to reset their password.
router.get('/ponastavitev-gesla', index.resetPassword)
// Confirm user email change.
router.get('/sprememba-elektronskega-naslova', index.changeEmail)
// Change user locale.
router.get('/spremeni-jezik/:languageCode', index.changeUserLanguage)
router.get('/moj-racun', isUserAuthenticated, index.myProfile)
router.get('/izbrisi-racun', isUserAuthenticated, index.deleteProfile)
@@ -119,9 +68,7 @@ router.get('/spremeni-geslo', isUserAuthenticated, index.changePassword)
router.get('/nastavitve-racuna', isUserAuthenticated, index.userSettings)
router.get('/ponastavitev-gesla', index.resetPassword)
// Change user locale.
router.get('/spremeni-jezik/:languageCode', index.changeUserLanguage)
// Log the user out.
router.post('/users/logout', isUserAuthenticated, user.logout)
module.exports = router