diff --git a/install/package.json b/install/package.json index cf85ac1842..d5581b8c1e 100644 --- a/install/package.json +++ b/install/package.json @@ -67,7 +67,7 @@ "daemon": "1.1.0", "diff": "8.0.3", "esbuild": "0.27.3", - "express": "4.22.1", + "express": "5.1.0", "express-session": "1.19.0", "express-useragent": "2.1.0", "fetch-cookie": "3.2.0", diff --git a/src/controllers/home.js b/src/controllers/home.js index e01c780e38..d8e3fb948d 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -1,5 +1,8 @@ 'use strict'; + +const querystring = require('querystring'); + const plugins = require('../plugins'); const meta = require('../meta'); const user = require('../user'); @@ -38,11 +41,13 @@ async function rewrite(req, res, next) { const pathname = parsedUrl.pathname.replace(/^\/+/, ''); const hook = `action:homepage.get:${pathname}`; if (!plugins.hooks.hasListeners(hook)) { - req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname; + const queryString = querystring.stringify(req.query); + req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname + (queryString ? `?${queryString}` : ''); } else { res.locals.homePageRoute = pathname; } - req.query = Object.assign(Object.fromEntries(parsedUrl.searchParams), req.query); + // TODO: cant write to req.query in express 5.x + // req.query = Object.assign(Object.fromEntries(parsedUrl.searchParams), req.query); next(); } diff --git a/src/middleware/index.js b/src/middleware/index.js index aa4c456c91..b2bef3c758 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -183,7 +183,8 @@ middleware.exposeUid = helpers.try(async (req, res, next) => { }); async function expose(exposedField, method, field, req, res, next) { - if (!req.params.hasOwnProperty(field)) { + const _params = { ...req.params }; + if (!_params.hasOwnProperty(field)) { return next(); } const param = String(req.params[field]).toLowerCase(); diff --git a/src/posts/recent.js b/src/posts/recent.js index 2ad84b0c7c..fc114cd9b2 100644 --- a/src/posts/recent.js +++ b/src/posts/recent.js @@ -15,7 +15,7 @@ module.exports = function (Posts) { Posts.getRecentPosts = async function (uid, start, stop, term) { let min = 0; - if (terms[term]) { + if (terms.hasOwnProperty(term) && term[term]) { min = Date.now() - terms[term]; } diff --git a/src/routes/activitypub.js b/src/routes/activitypub.js index 6c13fea365..e26379eefb 100644 --- a/src/routes/activitypub.js +++ b/src/routes/activitypub.js @@ -47,13 +47,14 @@ module.exports = function (app, middleware, controllers) { app.get('/post/:pid', [...middlewares, middleware.assert.post], helpers.tryRoute(controllers.activitypub.actors.note)); app.get('/post/:pid/replies', [...middlewares, middleware.assert.post], helpers.tryRoute(controllers.activitypub.actors.replies)); - app.get('/topic/:tid/:slug?', [...middlewares, middleware.assert.topic], helpers.tryRoute(controllers.activitypub.actors.topic)); + app.get('/topic/:tid/{:slug}', [...middlewares, middleware.assert.topic], helpers.tryRoute(controllers.activitypub.actors.topic)); app.get('/category/:cid/inbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.getInbox)); app.post('/category/:cid/inbox', [...inboxMiddlewares, middleware.assert.category, ...inboxMiddlewares], helpers.tryRoute(controllers.activitypub.postInbox)); app.get('/category/:cid/outbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.getCategoryOutbox)); app.post('/category/:cid/outbox', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.postOutbox)); - app.get('/category/:cid/:slug?', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.actors.category)); + app.get('/category/:cid/{:slug}', [...middlewares, middleware.assert.category], helpers.tryRoute(controllers.activitypub.actors.category)); + app.get('/message/:mid', [...middlewares, middleware.assert.message], helpers.tryRoute(controllers.activitypub.actors.message)); }; diff --git a/src/routes/admin.js b/src/routes/admin.js index 96cc92c62d..ea973759c3 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -18,7 +18,7 @@ module.exports = function (app, name, middleware, controllers) { helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id/analytics`, middlewares, controllers.admin.categories.getAnalytics); helpers.setupAdminPageRoute(app, `/${name}/manage/categories/:category_id/federation`, middlewares, controllers.admin.categories.getFederation); - helpers.setupAdminPageRoute(app, `/${name}/manage/privileges/:cid?`, middlewares, controllers.admin.privileges.get); + helpers.setupAdminPageRoute(app, `/${name}/manage/privileges{/:cid}`, middlewares, controllers.admin.privileges.get); helpers.setupAdminPageRoute(app, `/${name}/manage/tags`, middlewares, controllers.admin.tags.get); helpers.setupAdminPageRoute(app, `/${name}/manage/users`, middlewares, controllers.admin.users.index); diff --git a/src/routes/api.js b/src/routes/api.js index 79fb83b811..bb35c368f4 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -18,7 +18,7 @@ module.exports = function (app, middleware, controllers) { router.get('/user/email/:email', [...middlewares, middleware.canViewUsers], helpers.tryRoute(controllers.user.getUserByEmail)); router.get('/categories/:cid/moderators', [...middlewares], helpers.tryRoute(controllers.api.getModerators)); - router.get('/recent/posts/:term?', [...middlewares], helpers.tryRoute(controllers.posts.getRecentPosts)); + router.get('/recent/posts{/:term}', [...middlewares], helpers.tryRoute(controllers.posts.getRecentPosts)); router.get('/unread/total', [...middlewares, middleware.ensureLoggedIn], helpers.tryRoute(controllers.unread.unreadTotal)); router.get('/topic/teaser/:topic_id', [...middlewares], helpers.tryRoute(controllers.topics.teaser)); router.get('/topic/pagination/:topic_id', [...middlewares], helpers.tryRoute(controllers.topics.pagination)); diff --git a/src/routes/index.js b/src/routes/index.js index 71f722f397..9c551aae51 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -36,7 +36,7 @@ _mounts.main = (app, middleware, controllers) => { setupPageRoute(app, '/confirm/:code', [], controllers.confirmEmail); setupPageRoute(app, '/outgoing', [], controllers.outgoing); setupPageRoute(app, '/search', [], controllers.search.search); - setupPageRoute(app, '/reset/:code?', [middleware.delayLoading], controllers.reset); + setupPageRoute(app, '/reset{/:code}', [middleware.delayLoading], controllers.reset); setupPageRoute(app, '/tos', [], controllers.termsOfUse); setupPageRoute(app, '/email/unsubscribe/:token', [], controllers.accounts.settings.unsubscribe); @@ -48,7 +48,7 @@ _mounts.main = (app, middleware, controllers) => { _mounts.mod = (app, middleware, controllers) => { setupPageRoute(app, '/flags', [], controllers.mods.flags.list); setupPageRoute(app, '/flags/:flagId', [], controllers.mods.flags.detail); - setupPageRoute(app, '/post-queue/:id?', [], controllers.mods.postQueue); + setupPageRoute(app, '/post-queue{/:id}', [], controllers.mods.postQueue); }; _mounts.globalMod = (app, middleware, controllers) => { @@ -57,8 +57,8 @@ _mounts.globalMod = (app, middleware, controllers) => { }; _mounts.topic = (app, name, middleware, controllers) => { - setupPageRoute(app, `/${name}/:topic_id/:slug/:post_index?`, [], controllers.topics.get); - setupPageRoute(app, `/${name}/:topic_id/:slug?`, [], controllers.topics.get); + setupPageRoute(app, `/${name}/:topic_id/:slug{/:post_index}`, [], controllers.topics.get); + setupPageRoute(app, `/${name}/:topic_id{/:slug}`, [], controllers.topics.get); }; _mounts.post = (app, name, middleware, controllers) => { @@ -86,7 +86,7 @@ _mounts.categories = (app, name, middleware, controllers) => { _mounts.category = (app, name, middleware, controllers) => { setupPageRoute(app, `/${name}/:category_id/:slug/:topic_index`, [], controllers.category.get); - setupPageRoute(app, `/${name}/:category_id/:slug?`, [], controllers.category.get); + setupPageRoute(app, `/${name}/:category_id{/:slug}`, [], controllers.category.get); }; _mounts.users = (app, name, middleware, controllers) => { @@ -131,9 +131,13 @@ module.exports = async function (app, middleware) { } }); - router.all('(/+api|/+api/*?)', middleware.prepareAPI); - router.all(`(/+api/admin|/+api/admin/*?${mounts.admin !== 'admin' ? `|/+api/${mounts.admin}|/+api/${mounts.admin}/*?` : ''})`, middleware.authenticateRequest, middleware.ensureLoggedIn, middleware.admin.checkPrivileges); - router.all(`(/+admin|/+admin/*?${mounts.admin !== 'admin' ? `|/+${mounts.admin}|/+${mounts.admin}/*?` : ''})`, middleware.ensureLoggedIn, middleware.applyCSRF, middleware.admin.checkPrivileges); + // TODO: upgrade these routes to express 5.x + // router.all('(/+api|/+api/*?)', middleware.prepareAPI); + router.all(['/api/*splat', '/api'], middleware.prepareAPI); + + // router.all(`(/+api/admin|/+api/admin/*?${mounts.admin !== 'admin' ? `|/+api/${mounts.admin}|/+api/${mounts.admin}/*?` : ''})`, middleware.authenticateRequest, middleware.ensureLoggedIn, middleware.admin.checkPrivileges); + + // router.all(`(/+admin|/+admin/*?${mounts.admin !== 'admin' ? `|/+${mounts.admin}|/+${mounts.admin}/*?` : ''})`, middleware.ensureLoggedIn, middleware.applyCSRF, middleware.admin.checkPrivileges); app.use(middleware.stripLeadingSlashes); @@ -195,8 +199,8 @@ function addCoreRoutes(app, router, middleware, mounts) { res.redirect(`${relativePath}/assets/plugins${req.path}${req._parsedUrl.search || ''}`); }); - app.use(`${relativePath}/assets/client-*.css`, middleware.buildSkinAsset); - app.use(`${relativePath}/assets/client-*-rtl.css`, middleware.buildSkinAsset); + app.use(`${relativePath}/assets/client-*splat.css`, middleware.buildSkinAsset); + app.use(`${relativePath}/assets/client-*splat-rtl.css`, middleware.buildSkinAsset); app.use(controllers['404'].handle404); app.use(controllers.errors.handleURIErrors); diff --git a/src/routes/user.js b/src/routes/user.js index c2d1cc6f32..c933767d37 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -17,8 +17,8 @@ module.exports = function (app, name, middleware, controllers) { ]; setupPageRoute(app, '/me', [], middleware.redirectMeToUserslug); - setupPageRoute(app, '/me/*', [], middleware.redirectMeToUserslug); - setupPageRoute(app, '/uid/:uid*', [], middleware.redirectUidToUserslug); + setupPageRoute(app, '/me/*splat', [], middleware.redirectMeToUserslug); + setupPageRoute(app, '/uid{/:uid}', [], middleware.redirectUidToUserslug); setupPageRoute(app, `/${name}/:userslug`, middlewares, controllers.accounts.profile.get); setupPageRoute(app, `/${name}/:userslug/following`, middlewares, controllers.accounts.follow.getFollowing); @@ -51,8 +51,8 @@ module.exports = function (app, name, middleware, controllers) { setupPageRoute(app, `/${name}/:userslug/sessions`, accountMiddlewares, controllers.accounts.sessions.get); setupPageRoute(app, '/notifications', [middleware.ensureLoggedIn], controllers.accounts.notifications.get); - setupPageRoute(app, `/${name}/:userslug/chats/:roomid?/:index?`, [middleware.exposeUid, middleware.canViewUsers], controllers.accounts.chats.get); - setupPageRoute(app, '/chats/:roomid?/:index?', [middleware.ensureLoggedIn], controllers.accounts.chats.redirectToChat); + setupPageRoute(app, `/${name}/:userslug/chats{/:roomid}{/:index}`, [middleware.exposeUid, middleware.canViewUsers], controllers.accounts.chats.get); + setupPageRoute(app, '/chats{/:roomid}{/:index}', [middleware.ensureLoggedIn], controllers.accounts.chats.redirectToChat); setupPageRoute(app, `/message/:mid`, [middleware.ensureLoggedIn], controllers.accounts.chats.redirectToMessage); }; diff --git a/src/routes/well-known.js b/src/routes/well-known.js index a3edee27af..efe397429e 100644 --- a/src/routes/well-known.js +++ b/src/routes/well-known.js @@ -26,7 +26,7 @@ module.exports = function (app, middleware, controllers) { }); }); - app.get('/nodeinfo/2.0(.json)?', helpers.tryRoute(async (req, res) => { + app.get('/nodeinfo/2.0{.json}', helpers.tryRoute(async (req, res) => { const getDaysInMonth = (year, month) => new Date(year, month, 0).getDate(); function addMonths(input, months) { diff --git a/src/routes/write/posts.js b/src/routes/write/posts.js index ed2c372461..13a55da0d6 100644 --- a/src/routes/write/posts.js +++ b/src/routes/write/posts.js @@ -50,7 +50,8 @@ module.exports = function () { setupApiRoute(router, 'post', '/owner', [middleware.ensureLoggedIn, middleware.checkRequired.bind(null, ['pids', 'uid'])], controllers.write.posts.changeOwner); // Shorthand route to access post routes by topic index - router.all('/+byIndex/:index*?', [middleware.checkRequired.bind(null, ['tid'])], controllers.write.posts.redirectByIndex); + // TODO: upgrade to express 5 + // router.all('/+byIndex/:index*?', [middleware.checkRequired.bind(null, ['tid'])], controllers.write.posts.redirectByIndex); return router; }; diff --git a/src/routes/write/users.js b/src/routes/write/users.js index 139ed483c3..d52933ec7f 100644 --- a/src/routes/write/users.js +++ b/src/routes/write/users.js @@ -62,7 +62,8 @@ function authenticatedRoutes() { setupApiRoute(router, 'post', '/:uid/exports/:type', [...middlewares, middleware.assert.user, middleware.checkAccountPermissions], controllers.write.users.generateExportsByType); // Shorthand route to access user routes by userslug - router.all('/+bySlug/:userslug*?', [], controllers.write.users.redirectBySlug); + // TODO: upgrade to express 5 + // router.all('/+bySlug/:userslug*?', [], controllers.write.users.redirectBySlug); } module.exports = function () {