Skip to content

Latest commit

 

History

History
223 lines (217 loc) · 34.5 KB

webapi.md

File metadata and controls

223 lines (217 loc) · 34.5 KB

Generated by overleaf/services/web/bin/routes

Neglected API

  • [app/src/Features/Analytics/AnalyticsRouter.js]
  • [app/src/Features/Contacts/ContactRouter.js]
  • [app/src/Features/PasswordReset/PasswordResetRouter.js]
  • [app/src/Features/LinkedFiles/LinkedFilesRouter.js]
  • [app/src/Features/StaticPages/StaticPagesRouter.js]
  • [app/src/Features/Subscription/SubscriptionRouter.js]
  • [app/src/Features/Templates/TemplatesRouter.js]
  • [app/src/Features/UserMembership/UserMembershipRouter.js]
  • [modules/launchpad/app/src/LaunchpadRouter.js]
  • [modules/user-activate/app/src/UserActivateRouter.js]

Plan API

  • [app/src/Features/Collaborators/CollaboratorsRouter.js]

    webRouter      .post  : /project/:Project_id/leave => AuthenticationController.requireLogin() => CollaboratorsController.removeSelfFromProject
    webRouter      .put   : /project/:Project_id/users/:user_id => AuthenticationController.requireLogin() => validate({params:Joi.object({Project_id:Joi.objectId(),user_id:Joi.objectId()}),body:Joi.object({privilegeLevel:Joi.string().valid(PrivilegeLevels.READ_ONLY,PrivilegeLevels.READ_AND_WRITE).required()})}) => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsController.setCollaboratorInfo
    webRouter      .delete        : /project/:Project_id/users/:user_id => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsController.removeUserFromProject
    webRouter      .get   : /project/:Project_id/members => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsController.getAllMembers
    webRouter      .post  : /project/:Project_id/transfer-ownership => AuthenticationController.requireLogin() => validate({params:Joi.object({Project_id:Joi.objectId()}),body:Joi.object({user_id:Joi.objectId()})}) => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsController.transferOwnership
    webRouter      .post  : /project/:Project_id/invite => RateLimiterMiddleware.rateLimit(rateLimiters.inviteToProjectByProjectId,{params:['Project_id']}) => RateLimiterMiddleware.rateLimit(rateLimiters.inviteToProjectByIp,{ipOnly:true}) => CaptchaMiddleware.validateCaptcha('invite') => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsInviteController.inviteToProject
    webRouter      .get   : /project/:Project_id/invites => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsInviteController.getAllInvites
    webRouter      .delete        : /project/:Project_id/invite/:invite_id => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsInviteController.revokeInvite
    webRouter      .post  : /project/:Project_id/invite/:invite_id/resend => RateLimiterMiddleware.rateLimit(rateLimiters.resendInvite,{params:['Project_id']}) => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => CollaboratorsInviteController.resendInvite
    webRouter      .get   : /project/:Project_id/invite/token/:token => AnalyticsRegistrationSourceMiddleware.setSource('collaboration','project-invite') => AuthenticationController.requireLogin() => CollaboratorsInviteController.viewInvite => AnalyticsRegistrationSourceMiddleware.clearSource()
    webRouter      .post  : /project/:Project_id/invite/token/:token/accept => AnalyticsRegistrationSourceMiddleware.setSource('collaboration','project-invite') => AuthenticationController.requireLogin() => CollaboratorsInviteController.acceptInvite => AnalyticsRegistrationSourceMiddleware.clearSource()
    webRouter      .get   : /project/:Project_id/tokens => RateLimiterMiddleware.rateLimit(rateLimiters.getProjectTokens) => AuthorizationMiddleware.ensureUserCanReadProject => CollaboratorsController.getShareTokens
    
  • [app/src/Features/Editor/EditorRouter.js]

    webRouter      .post  : /project/:Project_id/doc => AuthorizationMiddleware.ensureUserCanWriteProjectContent => RateLimiterMiddleware.rateLimit(rateLimiters.addDocToProject,{params:['Project_id']}) => EditorHttpController.addDoc
    webRouter      .post  : /project/:Project_id/folder => AuthorizationMiddleware.ensureUserCanWriteProjectContent => RateLimiterMiddleware.rateLimit(rateLimiters.addFolderToProject,{params:['Project_id']}) => EditorHttpController.addFolder
    webRouter      .post  : /project/:Project_id/:entity_type/:entity_id/rename => AuthorizationMiddleware.ensureUserCanWriteProjectContent => EditorHttpController.renameEntity
    webRouter      .post  : /project/:Project_id/:entity_type/:entity_id/move => AuthorizationMiddleware.ensureUserCanWriteProjectContent => EditorHttpController.moveEntity
    webRouter      .delete        : /project/:Project_id/file/:entity_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => EditorHttpController.deleteFile
    webRouter      .delete        : /project/:Project_id/doc/:entity_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => EditorHttpController.deleteDoc
    webRouter      .delete        : /project/:Project_id/folder/:entity_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => EditorHttpController.deleteFolder
    privateApi     .post  : /project/:Project_id/join => AuthenticationController.requirePrivateApiAuth() => RateLimiterMiddleware.rateLimit(rateLimiters.joinProject,{params:['Project_id']}) => EditorHttpController.joinProject
    
  • [app/src/Features/Uploads/UploadsRouter.js]

    webRouter      .post  : /project/new/upload => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.projectUpload) => ProjectUploadController.multerMiddleware => ProjectUploadController.uploadProject
    webRouter      .post  : undefined => fileUploadRateLimit => AuthorizationMiddleware.ensureUserCanWriteProjectContent => ProjectUploadController.multerMiddleware => ProjectUploadController.uploadFile
    webRouter      .post  : undefined => fileUploadRateLimit => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanWriteProjectContent => ProjectUploadController.multerMiddleware => ProjectUploadController.uploadFile
    
  • [app/src/router.js]

    webRouter      .get   : * => AnalyticsRegistrationSourceMiddleware.setInbound()
    webRouter      .get   : * => AnalyticsUTMTrackingMiddleware.recordUTMTags()
    webRouter      .post  : /login/can-skip-captcha => RateLimiterMiddleware.rateLimit(rateLimiters.canSkipCaptcha) => CaptchaMiddleware.canSkipCaptcha
    webRouter      .get   : /login => UserPagesController.loginPage
    webRouter      .post  : /login => CaptchaMiddleware.validateCaptcha('login') => AuthenticationController.passportLogin
    webRouter      .get   : /login/legacy => UserPagesController.loginPage
    webRouter      .post  : /login/legacy => CaptchaMiddleware.validateCaptcha('login') => AuthenticationController.passportLogin
    webRouter      .get   : /read-only/one-time-login => UserPagesController.oneTimeLoginPage
    webRouter      .post  : /logout => UserController.logout
    webRouter      .get   : /restricted => AuthorizationMiddleware.restricted
    webRouter      .get   : /register => UserPagesController.registerPage
    webRouter      .get   : /user/bonus => AuthenticationController.requireLogin() => ReferalController.bonus
    webRouter      .get   : /system/messages => SystemMessageController.getMessages
    webRouter      .get   : /user/settings => AuthenticationController.requireLogin() => PermissionsController.useCapabilities() => UserPagesController.settingsPage
    webRouter      .post  : /user/settings => AuthenticationController.requireLogin() => UserController.updateUserSettings
    webRouter      .post  : /user/password/update => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.changePassword) => UserController.changePassword
    webRouter      .get   : /user/emails => AuthenticationController.requireLogin() => PermissionsController.useCapabilities() => UserController.promises.ensureAffiliationMiddleware => UserEmailsController.list
    webRouter      .get   : /user/emails/confirm => UserEmailsController.showConfirm
    webRouter      .post  : /user/emails/confirm => RateLimiterMiddleware.rateLimit(rateLimiters.confirmEmail) => UserEmailsController.confirm
    webRouter      .post  : /user/emails/resend_confirmation => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.resendConfirmation) => UserEmailsController.resendConfirmation
    webRouter      .get   : /user/emails/primary-email-check => AuthenticationController.requireLogin() => UserEmailsController.primaryEmailCheckPage
    webRouter      .post  : /user/emails/primary-email-check => AuthenticationController.requireLogin() => UserEmailsController.primaryEmailCheck
    webRouter      .post  : /user/emails => AuthenticationController.requireLogin() => PermissionsController.requirePermission('add-secondary-email') => RateLimiterMiddleware.rateLimit(rateLimiters.addEmail) => CaptchaMiddleware.validateCaptcha('addEmail') => UserEmailsController.add
    webRouter      .post  : /user/emails/delete => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.deleteEmail) => UserEmailsController.remove
    webRouter      .post  : /user/emails/default => AuthenticationController.requireLogin() => UserEmailsController.setDefault
    webRouter      .post  : /user/emails/endorse => AuthenticationController.requireLogin() => PermissionsController.requirePermission('endorse-email') => RateLimiterMiddleware.rateLimit(rateLimiters.endorseEmail) => UserEmailsController.endorse
    webRouter      .get   : /user/sessions => AuthenticationController.requireLogin() => UserPagesController.sessionsPage
    webRouter      .post  : /user/sessions/clear => AuthenticationController.requireLogin() => UserController.clearSessions
    webRouter      .delete        : /user/newsletter/unsubscribe => AuthenticationController.requireLogin() => UserController.unsubscribe
    webRouter      .post  : /user/newsletter/unsubscribe => AuthenticationController.requireLogin() => UserController.unsubscribe
    webRouter      .post  : /user/newsletter/subscribe => AuthenticationController.requireLogin() => UserController.subscribe
    webRouter      .get   : /user/email-preferences => AuthenticationController.requireLogin() => UserPagesController.emailPreferencesPage
    webRouter      .post  : /user/delete => RateLimiterMiddleware.rateLimit(rateLimiters.deleteUser) => AuthenticationController.requireLogin() => PermissionsController.requirePermission('delete-own-account') => UserController.tryDeleteUser
    webRouter      .get   : /user/personal_info => AuthenticationController.requireLogin() => UserInfoController.getLoggedInUsersPersonalInfo
    privateApi     .get   : /user/:user_id/personal_info => AuthenticationController.requirePrivateApiAuth() => UserInfoController.getPersonalInfo
    webRouter      .get   : /user/reconfirm => UserPagesController.renderReconfirmAccountPage
    webRouter      .get   : /user/tpds/queues => AuthenticationController.requireLogin() => TpdsController.getQueues
    webRouter      .get   : /user/projects => AuthenticationController.requireLogin() => ProjectController.userProjectsJson
    webRouter      .get   : /project/:Project_id/entities => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.projectEntitiesJson
    webRouter      .get   : /project => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.openDashboard) => ProjectListController.projectListPage
    webRouter      .post  : /project/new => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.createProject) => ProjectController.newProject
    webRouter      .post  : /api/project => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.getProjects) => ProjectListController.getProjectsJson
    webRouter      .get   : undefined => RateLimiterMiddleware.rateLimit(openProjectRateLimiter,{params:['Project_id']}) => AuthenticationController.validateUserSession() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.loadEditor
    webRouter      .head  : /Project/:Project_id/file/:File_id => AuthorizationMiddleware.ensureUserCanReadProject => FileStoreController.getFileHead
    webRouter      .get   : /Project/:Project_id/file/:File_id => AuthorizationMiddleware.ensureUserCanReadProject => FileStoreController.getFile
    webRouter      .post  : /project/:Project_id/settings => validate({body:Joi.object({publicAccessLevel:Joi.string().valid(PublicAccessLevels.PRIVATE,PublicAccessLevels.TOKEN_BASED).optional()})}) => AuthorizationMiddleware.ensureUserCanWriteProjectSettings => ProjectController.updateProjectSettings
    webRouter      .post  : /project/:Project_id/settings/admin => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => ProjectController.updateProjectAdminSettings
    webRouter      .post  : /project/:Project_id/compile => RateLimiterMiddleware.rateLimit(rateLimiters.compileProjectHttp,{params:['Project_id']}) => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.compile
    webRouter      .post  : /project/:Project_id/compile/stop => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.stopCompile
    webRouter      .get   : /project/:Project_id/output/output.pdf => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.downloadPdf
    webRouter      .get   : /^\/download\/project\/([^/]*)\/output\/output\.pdf$/ => function(req,res,next){const params={Project_id:req.params[0]};req.params=params;next();} => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.downloadPdf
    webRouter      .get   : /^\/download\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/output\.pdf$/ => function(req,res,next){const params={Project_id:req.params[0],build_id:req.params[1]};req.params=params;next();} => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.downloadPdf
    webRouter      .get   : /^\/project\/([^/]*)\/output\/(.*)$/ => function(req,res,next){const params={Project_id:req.params[0],file:req.params[1]};req.params=params;next();} => rateLimiterMiddlewareOutputFiles => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.getFileFromClsi
    webRouter      .get   : /^\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/ => function(req,res,next){const params={Project_id:req.params[0],build_id:req.params[1],file:req.params[2]};req.params=params;next();} => rateLimiterMiddlewareOutputFiles => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.getFileFromClsi
    webRouter      .get   : /^\/project\/([^/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/ => function(req,res,next){const params={Project_id:req.params[0],user_id:req.params[1],file:req.params[2]};req.params=params;next();} => rateLimiterMiddlewareOutputFiles => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.getFileFromClsi
    webRouter      .get   : /^\/project\/([^/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/ => function(req,res,next){const params={Project_id:req.params[0],user_id:req.params[1],build_id:req.params[2],file:req.params[3]};req.params=params;next();} => rateLimiterMiddlewareOutputFiles => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.getFileFromClsi
    webRouter      .delete        : /project/:Project_id/output => validate({query:{clsiserverid:Joi.string()}}) => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.deleteAuxFiles
    webRouter      .get   : /project/:Project_id/sync/code => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.proxySyncCode
    webRouter      .get   : /project/:Project_id/sync/pdf => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.proxySyncPdf
    webRouter      .get   : /project/:Project_id/wordcount => validate({query:{clsiserverid:Joi.string()}}) => AuthorizationMiddleware.ensureUserCanReadProject => CompileController.wordCount
    webRouter      .post  : /Project/:Project_id/archive => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.archiveProject
    webRouter      .delete        : /Project/:Project_id/archive => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.unarchiveProject
    webRouter      .post  : /project/:project_id/trash => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.trashProject
    webRouter      .delete        : /project/:project_id/trash => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.untrashProject
    webRouter      .delete        : /Project/:Project_id => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => ProjectController.deleteProject
    webRouter      .post  : /Project/:Project_id/restore => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => ProjectController.restoreProject
    webRouter      .post  : /Project/:Project_id/clone => AuthorizationMiddleware.ensureUserCanReadProject => ProjectController.cloneProject
    webRouter      .post  : /project/:Project_id/rename => AuthenticationController.requireLogin() => AuthorizationMiddleware.ensureUserCanAdminProject => ProjectController.renameProject
    webRouter      .get   : /project/:Project_id/updates => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.proxyToHistoryApiAndInjectUserDetails
    webRouter      .get   : /project/:Project_id/doc/:doc_id/diff => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.proxyToHistoryApi
    webRouter      .get   : /project/:Project_id/diff => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.proxyToHistoryApiAndInjectUserDetails
    webRouter      .get   : /project/:Project_id/filetree/diff => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.proxyToHistoryApi
    webRouter      .post  : /project/:Project_id/doc/:doc_id/version/:version_id/restore => AuthorizationMiddleware.ensureUserCanWriteProjectContent => HistoryController.proxyToHistoryApi
    webRouter      .post  : /project/:project_id/doc/:doc_id/restore => AuthorizationMiddleware.ensureUserCanWriteProjectContent => HistoryController.restoreDocFromDeletedDoc
    webRouter      .post  : /project/:project_id/restore_file => AuthorizationMiddleware.ensureUserCanWriteProjectContent => HistoryController.restoreFileFromV2
    webRouter      .get   : /project/:project_id/version/:version/zip => RateLimiterMiddleware.rateLimit(rateLimiters.downloadProjectRevision) => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.downloadZipOfVersion
    privateApi     .post  : /project/:Project_id/history/resync => AuthenticationController.requirePrivateApiAuth() => HistoryController.resyncProjectHistory
    webRouter      .get   : /project/:Project_id/labels => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => HistoryController.getLabels
    webRouter      .post  : /project/:Project_id/labels => AuthorizationMiddleware.ensureUserCanWriteProjectContent => HistoryController.createLabel
    webRouter      .delete        : /project/:Project_id/labels/:label_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => HistoryController.deleteLabel
    webRouter      .post  : /project/:project_id/export/:brand_variation_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => ExportsController.exportProject
    webRouter      .get   : /project/:project_id/export/:export_id => AuthorizationMiddleware.ensureUserCanWriteProjectContent => ExportsController.exportStatus
    webRouter      .get   : /project/:project_id/export/:export_id/:type => AuthorizationMiddleware.ensureUserCanWriteProjectContent => ExportsController.exportDownload
    webRouter      .get   : /Project/:Project_id/download/zip => RateLimiterMiddleware.rateLimit(rateLimiters.zipDownload,{params:['Project_id']}) => AuthorizationMiddleware.ensureUserCanReadProject => ProjectDownloadsController.downloadProject
    webRouter      .get   : /project/download/zip => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.multipleProjectsZipDownload) => AuthorizationMiddleware.ensureUserCanReadMultipleProjects => ProjectDownloadsController.downloadMultipleProjects
    webRouter      .get   : /project/:project_id/metadata => AuthorizationMiddleware.ensureUserCanReadProject => Settings.allowAnonymousReadAndWriteSharing?(req,res,next)=>{next();}:AuthenticationController.requireLogin() => MetaController.getMetadata
    webRouter      .post  : /project/:project_id/doc/:doc_id/metadata => AuthorizationMiddleware.ensureUserCanReadProject => Settings.allowAnonymousReadAndWriteSharing?(req,res,next)=>{next();}:AuthenticationController.requireLogin() => MetaController.broadcastMetadataForDoc
    privateApi     .post  : /internal/expire-deleted-projects-after-duration => AuthenticationController.requirePrivateApiAuth() => ProjectController.expireDeletedProjectsAfterDuration
    privateApi     .post  : /internal/expire-deleted-users-after-duration => AuthenticationController.requirePrivateApiAuth() => UserController.expireDeletedUsersAfterDuration
    privateApi     .post  : /internal/project/:projectId/expire-deleted-project => AuthenticationController.requirePrivateApiAuth() => ProjectController.expireDeletedProject
    privateApi     .post  : /internal/users/:userId/expire => AuthenticationController.requirePrivateApiAuth() => UserController.expireDeletedUser
    privateApi     .get   : /user/:userId/tag => AuthenticationController.requirePrivateApiAuth() => TagsController.apiGetAllTags
    webRouter      .get   : /tag => AuthenticationController.requireLogin() => TagsController.getAllTags
    webRouter      .post  : /tag => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.createTag) => validate({body:Joi.object({name:Joi.string().required(),color:Joi.string()})}) => TagsController.createTag
    webRouter      .post  : /tag/:tagId/rename => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.renameTag) => validate({body:Joi.object({name:Joi.string().required()})}) => TagsController.renameTag
    webRouter      .post  : /tag/:tagId/edit => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.renameTag) => validate({body:Joi.object({name:Joi.string().required(),color:Joi.string()})}) => TagsController.editTag
    webRouter      .delete        : /tag/:tagId => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.deleteTag) => TagsController.deleteTag
    webRouter      .post  : /tag/:tagId/project/:projectId => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.addProjectToTag) => TagsController.addProjectToTag
    webRouter      .post  : /tag/:tagId/projects => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.addProjectsToTag) => validate({body:Joi.object({projectIds:Joi.array().items(Joi.string()).required()})}) => TagsController.addProjectsToTag
    webRouter      .delete        : /tag/:tagId/project/:projectId => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectFromTag) => TagsController.removeProjectFromTag
    webRouter      .delete        : /tag/:tagId/projects => AuthenticationController.requireLogin() => RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectsFromTag) => validate({body:Joi.object({projectIds:Joi.array().items(Joi.string()).required()})}) => TagsController.removeProjectsFromTag
    webRouter      .get   : /notifications => AuthenticationController.requireLogin() => NotificationsController.getAllUnreadNotifications
    webRouter      .delete        : /notifications/:notificationId => AuthenticationController.requireLogin() => NotificationsController.markNotificationAsRead
    privateApi     .get   : /project/:project_id/details => AuthenticationController.requirePrivateApiAuth() => ProjectApiController.getProjectDetails
    privateApi     .get   : /internal/project/:project_id => AuthenticationController.requirePrivateApiAuth() => ProjectApiController.getProjectDetails
    privateApi     .get   : /internal/project/:Project_id/zip => AuthenticationController.requirePrivateApiAuth() => ProjectDownloadsController.downloadProject
    privateApi     .get   : /internal/project/:project_id/compile/pdf => AuthenticationController.requirePrivateApiAuth() => CompileController.compileAndDownloadPdf
    privateApi     .post  : /internal/deactivateOldProjects => AuthenticationController.requirePrivateApiAuth() => InactiveProjectController.deactivateOldProjects
    privateApi     .post  : /internal/project/:project_id/deactivate => AuthenticationController.requirePrivateApiAuth() => InactiveProjectController.deactivateProject
    privateApi     .get   : /^\/internal\/project\/([^/]*)\/output\/(.*)$/ => function(req,res,next){const params={Project_id:req.params[0],file:req.params[1]};req.params=params;next();} => AuthenticationController.requirePrivateApiAuth() => CompileController.getFileFromClsi
    privateApi     .get   : /project/:Project_id/doc/:doc_id => AuthenticationController.requirePrivateApiAuth() => DocumentController.getDocument
    privateApi     .post  : /project/:Project_id/doc/:doc_id => AuthenticationController.requirePrivateApiAuth() => DocumentController.setDocument
    privateApi     .post  : /user/:user_id/project/new => AuthenticationController.requirePrivateApiAuth() => TpdsController.createProject
    privateApi     .post  : /tpds/folder-update => AuthenticationController.requirePrivateApiAuth() => TpdsController.updateFolder
    privateApi     .post  : /user/:user_id/update/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.mergeUpdate
    privateApi     .delete        : /user/:user_id/update/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.deleteUpdate
    privateApi     .post  : /project/:project_id/user/:user_id/update/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.mergeUpdate
    privateApi     .delete        : /project/:project_id/user/:user_id/update/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.deleteUpdate
    privateApi     .post  : /project/:project_id/contents/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.updateProjectContents
    privateApi     .delete        : /project/:project_id/contents/* => AuthenticationController.requirePrivateApiAuth() => TpdsController.deleteProjectContents
    webRouter      .post  : /spelling/check => AuthenticationController.requireLogin() => SpellingController.proxyRequestToSpellingApi
    webRouter      .post  : /spelling/learn => validate({body:Joi.object({word:Joi.string().required()})}) => AuthenticationController.requireLogin() => SpellingController.learn
    webRouter      .post  : /spelling/unlearn => validate({body:Joi.object({word:Joi.string().required()})}) => AuthenticationController.requireLogin() => SpellingController.unlearn
    webRouter      .get   : /project/:project_id/messages => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => ChatController.getMessages
    webRouter      .post  : /project/:project_id/messages => AuthorizationMiddleware.blockRestrictedUserFromProject => AuthorizationMiddleware.ensureUserCanReadProject => RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage) => ChatController.sendMessage
    webRouter      .post  : /project/:Project_id/references/index => AuthorizationMiddleware.ensureUserCanReadProject => RateLimiterMiddleware.rateLimit(rateLimiters.indexProjectReferences) => ReferencesController.index
    webRouter      .post  : /project/:Project_id/references/indexAll => AuthorizationMiddleware.ensureUserCanReadProject => RateLimiterMiddleware.rateLimit(rateLimiters.indexAllProjectReferences) => ReferencesController.indexAll
    webRouter      .get   : /beta/participate => AuthenticationController.requireLogin() => BetaProgramController.optInPage
    webRouter      .post  : /beta/opt-in => AuthenticationController.requireLogin() => BetaProgramController.optIn
    webRouter      .post  : /beta/opt-out => AuthenticationController.requireLogin() => BetaProgramController.optOut
    publicApi      .post  : /api/clsi/compile/:submission_id => AuthenticationController.requirePrivateApiAuth() => CompileController.compileSubmission
    publicApi      .get   : /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/ => function(req,res,next){const params={submission_id:req.params[0],build_id:req.params[1],file:req.params[2]};req.params=params;next();} => AuthenticationController.requirePrivateApiAuth() => CompileController.getFileFromClsiWithoutUser
    publicApi      .post  : /api/institutions/confirm_university_domain => RateLimiterMiddleware.rateLimit(rateLimiters.confirmUniversityDomain) => AuthenticationController.requirePrivateApiAuth() => InstitutionsController.confirmDomain
    webRouter      .get   : /chrome => function(req,res,next){if(SessionManager.isUserLoggedIn(req.session)){res.redirect('/project');}else{res.redirect('/register');}}
    webRouter      .get   : /admin => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.index
    webRouter      .post  : /admin/openEditor => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.openEditor
    webRouter      .post  : /admin/closeEditor => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.closeEditor
    webRouter      .post  : /admin/disconnectAllUsers => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.disconnectAllUsers
    webRouter      .post  : /admin/flushProjectToTpds => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.flushProjectToTpds
    webRouter      .post  : /admin/pollDropboxForUser => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.pollDropboxForUser
    webRouter      .post  : /admin/messages => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.createMessage
    webRouter      .post  : /admin/messages/clear => AuthorizationMiddleware.ensureUserIsSiteAdmin => AdminController.clearMessages
    privateApi     .get   : /perfTest => (req,res)=>{plainTextResponse(res,'hello');}
    publicApi      .get   : /status => (req,res)=>{if(Settings.shuttingDown){res.sendStatus(503);}else if(!Settings.siteIsOpen){plainTextResponse(res,'web site is closed (web)');}else if(!Settings.editorIsOpen){plainTextResponse(res,'web editor is closed (web)');}else{plainTextResponse(res,'web sharelatex is alive (web)');}}
    privateApi     .get   : /status => (req,res)=>{plainTextResponse(res,'web sharelatex is alive (api)');}
    webRouter      .get   : /dev/csrf => (req,res)=>{plainTextResponse(res,res.locals.csrfToken);}
    publicApi      .get   : /health_check => HealthCheckController.checkActiveHandles => HealthCheckController.check
    privateApi     .get   : /health_check => HealthCheckController.checkActiveHandles => HealthCheckController.checkApi
    publicApi      .get   : /health_check/api => HealthCheckController.checkActiveHandles => HealthCheckController.checkApi
    privateApi     .get   : /health_check/api => HealthCheckController.checkActiveHandles => HealthCheckController.checkApi
    publicApi      .get   : /health_check/full => HealthCheckController.checkActiveHandles => HealthCheckController.check
    privateApi     .get   : /health_check/full => HealthCheckController.checkActiveHandles => HealthCheckController.check
    publicApi      .get   : /health_check/redis => HealthCheckController.checkRedis
    privateApi     .get   : /health_check/redis => HealthCheckController.checkRedis
    publicApi      .get   : /health_check/mongo => HealthCheckController.checkMongo
    privateApi     .get   : /health_check/mongo => HealthCheckController.checkMongo
    webRouter      .get   : /status/compiler/:Project_id => RateLimiterMiddleware.rateLimit(rateLimiters.statusCompiler) => AuthorizationMiddleware.ensureUserCanReadProject => function(req,res){const projectId=req.params.Project_id;const testUserId='123456789012345678901234';const sendRes=_.once(function(statusCode,message){res.status(statusCode);plainTextResponse(res,message);ClsiCookieManager.clearServerId(projectId,testUserId,()=>{});});let handler=setTimeout(function(){sendRes(500,'Compiler timed out');handler=null;},10000);CompileManager.compile(projectId,testUserId,{},function(error,status){if(handler){clearTimeout(handler);}if(error){sendRes(500,`Compiler returned error ${error.message}`);}else if(status==='success'){sendRes(200,'Compiler returned in less than 10 seconds');}else{sendRes(500,`Compiler returned failure ${status}`);}});}
    webRouter      .get   : /no-cache => function(req,res,next){res.header('Cache-Control','max-age=0');res.sendStatus(404);}
    webRouter      .get   : /oops-express => (req,res,next)=>next(new Error('Test error'))
    webRouter      .get   : /oops-internal => function(req,res,next){throw new Error('Test error');}
    webRouter      .get   : /oops-mongo => (req,res,next)=>require('./models/Project').Project.findOne({},function(){throw new Error('Test error');})
    privateApi     .get   : /opps-small => function(req,res,next){logger.err('test error occured');res.sendStatus(200);}
    webRouter      .post  : /error/client => function(req,res,next){logger.warn({err:req.body.error,meta:req.body.meta},'client side error');metrics.inc('client-side-error');res.sendStatus(204);}
    webRouter      .get   : undefined => RateLimiterMiddleware.rateLimit(rateLimiters.readOnlyToken) => AnalyticsRegistrationSourceMiddleware.setSource('collaboration','link-sharing') => TokenAccessController.tokenAccessPage => AnalyticsRegistrationSourceMiddleware.clearSource()
    webRouter      .get   : undefined => RateLimiterMiddleware.rateLimit(rateLimiters.readAndWriteToken) => AnalyticsRegistrationSourceMiddleware.setSource('collaboration','link-sharing') => TokenAccessController.tokenAccessPage => AnalyticsRegistrationSourceMiddleware.clearSource()
    webRouter      .post  : undefined => RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadWrite) => TokenAccessController.grantTokenAccessReadAndWrite
    webRouter      .post  : undefined => RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadOnly) => TokenAccessController.grantTokenAccessReadOnly
    webRouter      .get   : /unsupported-browser => renderUnsupportedBrowserPage
    webRouter      .get   : * => ErrorController.notFound