Merge pull request #17426 from overleaf/msm-expressify-controllers

[web] Expressify controller methods

GitOrigin-RevId: 9784176b53a89beed09f9b38915872a6e7fae465
This commit is contained in:
Miguel Serrano 2024-03-11 12:25:30 +01:00 committed by Copybot
parent d2cfa26807
commit 02d890ef18
5 changed files with 72 additions and 81 deletions

View file

@ -3,6 +3,7 @@ const AnalyticsManager = require('./AnalyticsManager')
const SessionManager = require('../Authentication/SessionManager') const SessionManager = require('../Authentication/SessionManager')
const GeoIpLookup = require('../../infrastructure/GeoIpLookup') const GeoIpLookup = require('../../infrastructure/GeoIpLookup')
const Features = require('../../infrastructure/Features') const Features = require('../../infrastructure/Features')
const { expressify } = require('@overleaf/promise-utils')
async function updateEditingSession(req, res, next) { async function updateEditingSession(req, res, next) {
if (!Features.hasFeature('analytics')) { if (!Features.hasFeature('analytics')) {
@ -46,6 +47,6 @@ function recordEvent(req, res, next) {
} }
module.exports = { module.exports = {
updateEditingSession, updateEditingSession: expressify(updateEditingSession),
recordEvent, recordEvent,
} }

View file

@ -3,7 +3,6 @@ const AnalyticsController = require('./AnalyticsController')
const AnalyticsProxy = require('./AnalyticsProxy') const AnalyticsProxy = require('./AnalyticsProxy')
const { RateLimiter } = require('../../infrastructure/RateLimiter') const { RateLimiter } = require('../../infrastructure/RateLimiter')
const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware') const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
const { expressify } = require('@overleaf/promise-utils')
const rateLimiters = { const rateLimiters = {
recordEvent: new RateLimiter('analytics-record-event', { recordEvent: new RateLimiter('analytics-record-event', {
@ -33,7 +32,7 @@ module.exports = {
RateLimiterMiddleware.rateLimit(rateLimiters.updateEditingSession, { RateLimiterMiddleware.rateLimit(rateLimiters.updateEditingSession, {
params: ['projectId'], params: ['projectId'],
}), }),
expressify(AnalyticsController.updateEditingSession) AnalyticsController.updateEditingSession
) )
publicApiRouter.use( publicApiRouter.use(

View file

@ -5,13 +5,14 @@ const {
} = require('./PermissionsManager') } = require('./PermissionsManager')
const { checkUserPermissions } = require('./PermissionsManager').promises const { checkUserPermissions } = require('./PermissionsManager').promises
const Modules = require('../../infrastructure/Modules') const Modules = require('../../infrastructure/Modules')
const { expressify } = require('@overleaf/promise-utils')
/** /**
* Function that returns middleware to add an `assertPermission` function to the request object to check if the user has a specific capability. * Function that returns middleware to add an `assertPermission` function to the request object to check if the user has a specific capability.
* @returns {Function} The middleware function that adds the `assertPermission` function to the request object. * @returns {Function} The middleware function that adds the `assertPermission` function to the request object.
*/ */
function useCapabilities() { function useCapabilities() {
return async function (req, res, next) { const middleware = async function (req, res, next) {
// attach the user's capabilities to the request object // attach the user's capabilities to the request object
req.capabilitySet = new Set() req.capabilitySet = new Set()
// provide a function to assert that a capability is present // provide a function to assert that a capability is present
@ -57,6 +58,7 @@ function useCapabilities() {
} }
} }
} }
return expressify(middleware)
} }
/** /**

View file

@ -1,18 +1,3 @@
/* eslint-disable
n/handle-callback-err,
max-len,
no-unused-vars,
n/no-deprecated-api,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let HomeController
const Features = require('../../infrastructure/Features') const Features = require('../../infrastructure/Features')
const AnalyticsManager = require('../Analytics/AnalyticsManager') const AnalyticsManager = require('../Analytics/AnalyticsManager')
@ -23,6 +8,7 @@ const ErrorController = require('../Errors/ErrorController')
const SessionManager = require('../Authentication/SessionManager') const SessionManager = require('../Authentication/SessionManager')
const SplitTestHandler = require('../SplitTests/SplitTestHandler') const SplitTestHandler = require('../SplitTests/SplitTestHandler')
const { expressify } = require('@overleaf/promise-utils')
const logger = require('@overleaf/logger') const logger = require('@overleaf/logger')
const homepageExists = fs.existsSync( const homepageExists = fs.existsSync(
@ -32,55 +18,57 @@ const homepageExists = fs.existsSync(
) )
) )
module.exports = HomeController = { async function index(req, res) {
index(req, res) { if (SessionManager.isUserLoggedIn(req.session)) {
if (SessionManager.isUserLoggedIn(req.session)) { if (req.query.scribtex_path != null) {
if (req.query.scribtex_path != null) { res.redirect(`/project?scribtex_path=${req.query.scribtex_path}`)
return res.redirect(`/project?scribtex_path=${req.query.scribtex_path}`)
} else {
return res.redirect('/project')
}
} else { } else {
return HomeController.home(req, res) res.redirect('/project')
} }
}, } else {
await home(req, res)
async home(req, res) { }
if (Features.hasFeature('homepage') && homepageExists) { }
const onboardingFlowAssignment =
await SplitTestHandler.promises.getAssignment( async function home(req, res) {
req, if (Features.hasFeature('homepage') && homepageExists) {
res, const onboardingFlowAssignment =
'onboarding-flow' await SplitTestHandler.promises.getAssignment(req, res, 'onboarding-flow')
) AnalyticsManager.recordEventForSession(req.session, 'home-page-view', {
AnalyticsManager.recordEventForSession(req.session, 'home-page-view', { page: req.path,
page: req.path, })
})
res.render('external/home/website-redesign/index', {
return res.render('external/home/website-redesign/index', { onboardingFlowVariant: onboardingFlowAssignment.variant,
onboardingFlowVariant: onboardingFlowAssignment.variant, hideNewsletterCheckbox:
hideNewsletterCheckbox: onboardingFlowAssignment.variant === 'token-confirmation-odc',
onboardingFlowAssignment.variant === 'token-confirmation-odc', })
}) } else {
} else { res.redirect('/login')
return res.redirect('/login') }
} }
},
function externalPage(page, title) {
externalPage(page, title) { const middleware = async function (req, res, next) {
return function (req, res, next) { const path = Path.join(__dirname, `/../../../views/external/${page}.pug`)
if (next == null) { try {
next = function () {} const stats = await fs.promises.stat(path)
} if (!stats.isFile()) {
const path = Path.join(__dirname, `/../../../views/external/${page}.pug`) logger.error({ stats, path }, 'Error serving external page')
return fs.exists(path, function (exists) { ErrorController.notFound(req, res, next)
// No error in this callback - old method in Node.js! } else {
if (exists) { res.render(`external/${page}.pug`, { title })
return res.render(`external/${page}.pug`, { title }) }
} else { } catch (error) {
return ErrorController.notFound(req, res, next) logger.error({ path }, 'Error serving external page: file not found')
} ErrorController.notFound(req, res, next)
}) }
} }
}, return expressify(middleware)
}
module.exports = {
index: expressify(index),
home: expressify(home),
externalPage,
} }

View file

@ -5,6 +5,7 @@ const modulePath = path.join(
'../../../../app/src/Features/Analytics/AnalyticsController' '../../../../app/src/Features/Analytics/AnalyticsController'
) )
const sinon = require('sinon') const sinon = require('sinon')
const MockResponse = require('../helpers/MockResponse')
describe('AnalyticsController', function () { describe('AnalyticsController', function () {
beforeEach(function () { beforeEach(function () {
@ -32,10 +33,7 @@ describe('AnalyticsController', function () {
}, },
}) })
this.res = { this.res = new MockResponse()
send() {},
sendStatus() {},
}
}) })
describe('updateEditingSession', function () { describe('updateEditingSession', function () {
@ -56,16 +54,19 @@ describe('AnalyticsController', function () {
.resolves({ country_code: 'XY' }) .resolves({ country_code: 'XY' })
}) })
it('delegates to the AnalyticsManager', async function () { it('delegates to the AnalyticsManager', function (done) {
this.SessionManager.getLoggedInUserId.returns('1234') this.SessionManager.getLoggedInUserId.returns('1234')
await this.controller.updateEditingSession(this.req, this.res) this.res.callback = () => {
sinon.assert.calledWith( sinon.assert.calledWith(
this.AnalyticsManager.updateEditingSession, this.AnalyticsManager.updateEditingSession,
'1234', '1234',
'a project id', 'a project id',
'XY', 'XY',
{ editorType: 'abc' } { editorType: 'abc' }
) )
done()
}
this.controller.updateEditingSession(this.req, this.res)
}) })
}) })