UserPagesController.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. const UserGetter = require('./UserGetter')
  2. const OError = require('@overleaf/o-error')
  3. const UserSessionsManager = require('./UserSessionsManager')
  4. const logger = require('@overleaf/logger')
  5. const Settings = require('@overleaf/settings')
  6. const AuthenticationController = require('../Authentication/AuthenticationController')
  7. const SessionManager = require('../Authentication/SessionManager')
  8. const _ = require('lodash')
  9. const UserPagesController = {
  10. registerPage(req, res) {
  11. const sharedProjectData = {
  12. project_name: req.query.project_name,
  13. user_first_name: req.query.user_first_name,
  14. }
  15. const newTemplateData = {}
  16. if (req.session.templateData != null) {
  17. newTemplateData.templateName = req.session.templateData.templateName
  18. }
  19. res.render('user/register', {
  20. title: 'register',
  21. sharedProjectData,
  22. newTemplateData,
  23. samlBeta: req.session.samlBeta,
  24. })
  25. },
  26. loginPage(req, res) {
  27. // if user is being sent to /login with explicit redirect (redir=/foo),
  28. // such as being sent from the editor to /login, then set the redirect explicitly
  29. if (
  30. req.query.redir != null &&
  31. AuthenticationController._getRedirectFromSession(req) == null
  32. ) {
  33. AuthenticationController.setRedirectInSession(req, req.query.redir)
  34. }
  35. res.render('user/login', {
  36. title: 'login',
  37. })
  38. },
  39. /**
  40. * Landing page for users who may have received one-time login
  41. * tokens from the read-only maintenance site.
  42. *
  43. * We tell them that Overleaf is back up and that they can login normally.
  44. */
  45. oneTimeLoginPage(req, res, next) {
  46. res.render('user/one_time_login')
  47. },
  48. logoutPage(req, res) {
  49. res.render('user/logout')
  50. },
  51. renderReconfirmAccountPage(req, res) {
  52. const pageData = {
  53. reconfirm_email: req.session.reconfirm_email,
  54. }
  55. // when a user must reconfirm their account
  56. res.render('user/reconfirm', pageData)
  57. },
  58. settingsPage(req, res, next) {
  59. const userId = SessionManager.getLoggedInUserId(req.session)
  60. const reconfirmationRemoveEmail = req.query.remove
  61. // SSO
  62. const ssoError = req.session.ssoError
  63. if (ssoError) {
  64. delete req.session.ssoError
  65. }
  66. // Institution SSO
  67. let institutionLinked = _.get(req.session, ['saml', 'linked'])
  68. if (institutionLinked) {
  69. // copy object if exists because _.get does not
  70. institutionLinked = Object.assign(
  71. {
  72. hasEntitlement: _.get(req.session, ['saml', 'hasEntitlement']),
  73. },
  74. institutionLinked
  75. )
  76. }
  77. const samlError = _.get(req.session, ['saml', 'error'])
  78. const institutionEmailNonCanonical = _.get(req.session, [
  79. 'saml',
  80. 'emailNonCanonical',
  81. ])
  82. const institutionRequestedEmail = _.get(req.session, [
  83. 'saml',
  84. 'requestedEmail',
  85. ])
  86. const reconfirmedViaSAML = _.get(req.session, ['saml', 'reconfirmed'])
  87. delete req.session.saml
  88. let shouldAllowEditingDetails = true
  89. if (Settings.ldap && Settings.ldap.updateUserDetailsOnLogin) {
  90. shouldAllowEditingDetails = false
  91. }
  92. if (Settings.saml && Settings.saml.updateUserDetailsOnLogin) {
  93. shouldAllowEditingDetails = false
  94. }
  95. const oauthProviders = Settings.oauthProviders || {}
  96. UserGetter.getUser(userId, (err, user) => {
  97. if (err != null) {
  98. return next(err)
  99. }
  100. if (!user) {
  101. // The user has just deleted their account.
  102. return res.redirect('/logout')
  103. }
  104. res.render('user/settings', {
  105. title: 'account_settings',
  106. user,
  107. hasPassword: !!user.hashedPassword,
  108. shouldAllowEditingDetails,
  109. languages: Settings.languages,
  110. accountSettingsTabActive: true,
  111. oauthProviders: UserPagesController._translateProviderDescriptions(
  112. oauthProviders,
  113. req
  114. ),
  115. oauthUseV2: Settings.oauthUseV2 || false,
  116. institutionLinked,
  117. samlError,
  118. institutionEmailNonCanonical:
  119. institutionEmailNonCanonical && institutionRequestedEmail
  120. ? institutionEmailNonCanonical
  121. : undefined,
  122. reconfirmedViaSAML,
  123. reconfirmationRemoveEmail,
  124. samlBeta: req.session.samlBeta,
  125. ssoError: ssoError,
  126. thirdPartyIds: UserPagesController._restructureThirdPartyIds(user),
  127. })
  128. })
  129. },
  130. sessionsPage(req, res, next) {
  131. const user = SessionManager.getSessionUser(req.session)
  132. logger.log({ userId: user._id }, 'loading sessions page')
  133. const currentSession = {
  134. ip_address: user.ip_address,
  135. session_created: user.session_created,
  136. }
  137. UserSessionsManager.getAllUserSessions(
  138. user,
  139. [req.sessionID],
  140. (err, sessions) => {
  141. if (err != null) {
  142. OError.tag(err, 'error getting all user sessions', {
  143. userId: user._id,
  144. })
  145. return next(err)
  146. }
  147. res.render('user/sessions', {
  148. title: 'sessions',
  149. currentSession,
  150. sessions,
  151. })
  152. }
  153. )
  154. },
  155. _restructureThirdPartyIds(user) {
  156. // 3rd party identifiers are an array of objects
  157. // this turn them into a single object, which
  158. // makes data easier to use in template
  159. if (
  160. !user.thirdPartyIdentifiers ||
  161. user.thirdPartyIdentifiers.length === 0
  162. ) {
  163. return null
  164. }
  165. return user.thirdPartyIdentifiers.reduce((obj, identifier) => {
  166. obj[identifier.providerId] = identifier.externalUserId
  167. return obj
  168. }, {})
  169. },
  170. _translateProviderDescriptions(providers, req) {
  171. const result = {}
  172. if (providers) {
  173. for (const provider in providers) {
  174. const data = providers[provider]
  175. data.description = req.i18n.translate(
  176. data.descriptionKey,
  177. Object.assign({}, data.descriptionOptions)
  178. )
  179. result[provider] = data
  180. }
  181. }
  182. return result
  183. },
  184. }
  185. module.exports = UserPagesController