Remove node controller and dead backend code of the old project list (#12222)

GitOrigin-RevId: 31f92b1df484db9e44ea17cd258fdc5fe467a379
This commit is contained in:
M Fahru
2023-05-26 08:05:10 +00:00
committed by Copybot
parent 3e315eada1
commit c1211bef8f
2 changed files with 0 additions and 896 deletions
@@ -11,9 +11,7 @@ const EditorController = require('../Editor/EditorController')
const ProjectHelper = require('./ProjectHelper')
const metrics = require('@overleaf/metrics')
const { User } = require('../../models/User')
const TagsHandler = require('../Tags/TagsHandler')
const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
const NotificationsHandler = require('../Notifications/NotificationsHandler')
const LimitationsManager = require('../Subscription/LimitationsManager')
const Settings = require('@overleaf/settings')
const AuthorizationManager = require('../Authorization/AuthorizationManager')
@@ -28,21 +26,15 @@ const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
const ProjectEntityHandler = require('./ProjectEntityHandler')
const TpdsProjectFlusher = require('../ThirdPartyDataStore/TpdsProjectFlusher')
const UserGetter = require('../User/UserGetter')
const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
const { V1ConnectionError } = require('../Errors/Errors')
const Features = require('../../infrastructure/Features')
const BrandVariationsHandler = require('../BrandVariations/BrandVariationsHandler')
const UserController = require('../User/UserController')
const AnalyticsManager = require('../Analytics/AnalyticsManager')
const Modules = require('../../infrastructure/Modules')
const SplitTestHandler = require('../SplitTests/SplitTestHandler')
const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
const SpellingHandler = require('../Spelling/SpellingHandler')
const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
const InstitutionsFeatures = require('../Institutions/InstitutionsFeatures')
const SubscriptionViewModelBuilder = require('../Subscription/SubscriptionViewModelBuilder')
const SurveyHandler = require('../Survey/SurveyHandler')
const ProjectAuditLogHandler = require('./ProjectAuditLogHandler')
const PublicAccessLevels = require('../Authorization/PublicAccessLevels')
@@ -54,25 +46,6 @@ const VISUAL_EDITOR_NAMING_SPLIT_TEST_MIN_SIGNUP_DATE = new Date('2023-04-17')
* @typedef {import("./types").Project} Project
*/
const _ssoAvailable = (affiliation, session, linkedInstitutionIds) => {
if (!affiliation.institution) return false
// institution.confirmed is for the domain being confirmed, not the email
// Do not show SSO UI for unconfirmed domains
if (!affiliation.institution.confirmed) return false
// Could have multiple emails at the same institution, and if any are
// linked to the institution then do not show notification for others
if (
linkedInstitutionIds.indexOf(affiliation.institution.id.toString()) === -1
) {
if (affiliation.institution.ssoEnabled) return true
if (affiliation.institution.ssoBeta && session.samlBeta) return true
return false
}
return false
}
const ProjectController = {
_isInPercentageRollout(rolloutName, objectId, percentage) {
if (Settings.bypassPercentageRollouts === true) {
@@ -413,331 +386,6 @@ const ProjectController = {
})
},
projectListPage(req, res, next) {
const timer = new metrics.Timer('project-list')
const userId = SessionManager.getLoggedInUserId(req.session)
const currentUser = SessionManager.getSessionUser(req.session)
async.parallel(
{
tags(cb) {
TagsHandler.getAllTags(userId, cb)
},
notifications(cb) {
NotificationsHandler.getUserNotifications(userId, cb)
},
projects(cb) {
ProjectGetter.findAllUsersProjects(
userId,
'name lastUpdated lastUpdatedBy publicAccesLevel archived trashed owner_ref tokens',
cb
)
},
hasSubscription(cb) {
LimitationsManager.hasPaidSubscription(
currentUser,
(error, hasPaidSubscription) => {
if (error != null && error instanceof V1ConnectionError) {
return cb(null, true)
}
cb(error, hasPaidSubscription)
}
)
},
user(cb) {
User.findById(
userId,
'email emails featureSwitches overleaf awareOfV2 features lastLoginIp lastPrimaryEmailCheck signUpDate',
cb
)
},
userEmailsData(cb) {
const result = { list: [], allInReconfirmNotificationPeriods: [] }
UserGetter.getUserFullEmails(userId, (error, fullEmails) => {
if (error && error instanceof V1ConnectionError) {
return cb(null, result)
}
if (!Features.hasFeature('affiliations')) {
result.list = fullEmails
return cb(null, result)
}
Modules.hooks.fire(
'allInReconfirmNotificationPeriodsForUser',
fullEmails,
(error, results) => {
if (error != null) {
return cb(error)
}
// Module.hooks.fire accepts multiple methods
// and does async.series
const allInReconfirmNotificationPeriods =
(results && results[0]) || []
cb(null, {
list: fullEmails,
allInReconfirmNotificationPeriods,
})
}
)
})
},
usersBestSubscription(cb) {
if (!Features.hasFeature('saas')) {
return cb()
}
SubscriptionViewModelBuilder.getBestSubscription(
{ _id: userId },
(err, subscription) => {
if (err) {
// do not fail loading the project list when fetching the best subscription fails
logger.error(
{ userId, err },
'Could not get usersBestSubscription'
)
return cb(null, { type: 'error' })
}
cb(null, subscription)
}
)
},
userIsMemberOfGroupSubscription(cb) {
LimitationsManager.userIsMemberOfGroupSubscription(
currentUser,
(error, isMember) => {
if (error) {
logger.error(
{ err: error },
'Failed to check whether user is a member of group subscription'
)
return cb(null, false)
}
cb(null, isMember)
}
)
},
survey(cb) {
SurveyHandler.getSurvey(userId, (err, survey) => {
if (err) {
logger.warn({ err }, 'failed to get survey')
// do not fail loading the project list if we fail to load the survey
cb(null, null)
} else {
cb(null, survey)
}
})
},
},
(err, results) => {
if (err != null) {
OError.tag(err, 'error getting data for project list page')
return next(err)
}
const {
notifications,
user,
userEmailsData,
userIsMemberOfGroupSubscription,
} = results
if (
user &&
Features.hasFeature('saas') &&
UserPrimaryEmailCheckHandler.requiresPrimaryEmailCheck(user)
) {
return res.redirect('/user/emails/primary-email-check')
}
const userEmails = userEmailsData.list || []
const userAffiliations = userEmails
.filter(emailData => !!emailData.affiliation)
.map(emailData => {
const result = emailData.affiliation
result.email = emailData.email
return result
})
const { allInReconfirmNotificationPeriods } = userEmailsData
// Handle case of deleted user
if (user == null) {
UserController.logout(req, res, next)
return
}
const tags = results.tags
const notificationsInstitution = []
for (const notification of notifications) {
notification.html = req.i18n.translate(
notification.templateKey,
notification.messageOpts
)
}
// Institution SSO Notifications
let reconfirmedViaSAML
if (Features.hasFeature('saml')) {
reconfirmedViaSAML = _.get(req.session, ['saml', 'reconfirmed'])
const samlSession = req.session.saml
// Notification: SSO Available
const linkedInstitutionIds = []
user.emails.forEach(email => {
if (email.samlProviderId) {
linkedInstitutionIds.push(email.samlProviderId)
}
})
if (Array.isArray(userAffiliations)) {
userAffiliations.forEach(affiliation => {
if (
_ssoAvailable(affiliation, req.session, linkedInstitutionIds)
) {
notificationsInstitution.push({
email: affiliation.email,
institutionId: affiliation.institution.id,
institutionName: affiliation.institution.name,
templateKey: 'notification_institution_sso_available',
})
}
})
}
if (samlSession) {
// Notification: After SSO Linked
if (samlSession.linked) {
notificationsInstitution.push({
email: samlSession.institutionEmail,
institutionName: samlSession.linked.universityName,
templateKey: 'notification_institution_sso_linked',
})
}
// Notification: After SSO Linked or Logging in
// The requested email does not match primary email returned from
// the institution
if (
samlSession.requestedEmail &&
samlSession.emailNonCanonical &&
!samlSession.error
) {
notificationsInstitution.push({
institutionEmail: samlSession.emailNonCanonical,
requestedEmail: samlSession.requestedEmail,
templateKey: 'notification_institution_sso_non_canonical',
})
}
// Notification: Tried to register, but account already existed
// registerIntercept is set before the institution callback.
// institutionEmail is set after institution callback.
// Check for both in case SSO flow was abandoned
if (
samlSession.registerIntercept &&
samlSession.institutionEmail &&
!samlSession.error
) {
notificationsInstitution.push({
email: samlSession.institutionEmail,
templateKey: 'notification_institution_sso_already_registered',
})
}
// Notification: When there is a session error
if (samlSession.error) {
notificationsInstitution.push({
templateKey: 'notification_institution_sso_error',
error: samlSession.error,
})
}
}
delete req.session.saml
}
const portalTemplates =
ProjectController._buildPortalTemplatesList(userAffiliations)
const projects = ProjectController._buildProjectList(
results.projects,
userId
)
// in v2 add notifications for matching university IPs
if (Settings.overleaf != null && req.ip !== user.lastLoginIp) {
NotificationsBuilder.ipMatcherAffiliation(user._id).create(
req.ip,
() => {}
)
}
const hasPaidAffiliation = userAffiliations.some(
affiliation => affiliation.licence && affiliation.licence !== 'free'
)
const showGroupsAndEnterpriseBanner =
Features.hasFeature('saas') &&
!userIsMemberOfGroupSubscription &&
!hasPaidAffiliation
const groupsAndEnterpriseBannerVariant =
showGroupsAndEnterpriseBanner &&
_.sample(['did-you-know', 'on-premise', 'people', 'FOMO'])
ProjectController._injectProjectUsers(projects, (error, projects) => {
if (error != null) {
return next(error)
}
const viewModel = {
title: 'your_projects',
priority_title: true,
projects,
tags,
notifications: notifications || [],
notificationsInstitution,
allInReconfirmNotificationPeriods,
portalTemplates,
user,
userAffiliations,
userEmails,
hasSubscription: results.hasSubscription,
reconfirmedViaSAML,
zipFileSizeLimit: Settings.maxUploadSize,
isOverleaf: !!Settings.overleaf,
metadata: { viewport: false },
showThinFooter: true, // don't show the fat footer on the projects dashboard, as there's a fixed space available
usersBestSubscription: results.usersBestSubscription,
survey: results.survey,
showGroupsAndEnterpriseBanner,
groupsAndEnterpriseBannerVariant,
}
const paidUser =
(user.features != null ? user.features.github : undefined) &&
(user.features != null ? user.features.dropbox : undefined) // use a heuristic for paid account
const freeUserProportion = 0.1
const sampleFreeUser =
parseInt(user._id.toString().slice(-2), 16) <
freeUserProportion * 255
const showFrontWidget = paidUser || sampleFreeUser
if (showFrontWidget) {
viewModel.frontChatWidgetRoomId =
Settings.overleaf != null
? Settings.overleaf.front_chat_widget_room_id
: undefined
}
// null test targeting logged in users
SplitTestHandler.promises.getAssignment(
req,
res,
'null-test-dashboard'
)
res.render('project/list', viewModel)
timer.done()
})
}
)
},
loadEditor(req, res, next) {
const timer = new metrics.Timer('load-editor')
if (!Settings.editorIsOpen) {