UserPagesController.js 6.3 KB

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