Errors.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. const OError = require('@overleaf/o-error')
  2. const settings = require('@overleaf/settings')
  3. // Error class for legacy errors so they inherit OError while staying
  4. // backward-compatible (can be instantiated with string as argument instead
  5. // of object)
  6. class BackwardCompatibleError extends OError {
  7. /**
  8. * @param {string | { message: string, info?: Object }} messageOrOptions
  9. */
  10. constructor(messageOrOptions) {
  11. if (typeof messageOrOptions === 'string') {
  12. super(messageOrOptions)
  13. } else if (messageOrOptions) {
  14. const { message, info } = messageOrOptions
  15. super(message, info)
  16. } else {
  17. super()
  18. }
  19. }
  20. }
  21. // Error class that facilitates the migration to OError v3 by providing
  22. // a signature in which the 2nd argument can be an object containing
  23. // the `info` object.
  24. class OErrorV2CompatibleError extends OError {
  25. constructor(message, options) {
  26. if (options) {
  27. super(message, options.info)
  28. } else {
  29. super(message)
  30. }
  31. }
  32. }
  33. class NotFoundError extends BackwardCompatibleError {}
  34. class ForbiddenError extends BackwardCompatibleError {}
  35. class ServiceNotConfiguredError extends BackwardCompatibleError {}
  36. class TooManyRequestsError extends BackwardCompatibleError {}
  37. class ResourceGoneError extends BackwardCompatibleError {}
  38. class DuplicateNameError extends OError {}
  39. class InvalidNameError extends BackwardCompatibleError {}
  40. class UnsupportedFileTypeError extends BackwardCompatibleError {}
  41. class FileTooLargeError extends BackwardCompatibleError {}
  42. class UnsupportedExportRecordsError extends BackwardCompatibleError {}
  43. class V1HistoryNotSyncedError extends BackwardCompatibleError {}
  44. class ProjectHistoryDisabledError extends BackwardCompatibleError {}
  45. class V1ConnectionError extends BackwardCompatibleError {}
  46. class UnconfirmedEmailError extends BackwardCompatibleError {}
  47. class EmailExistsError extends OErrorV2CompatibleError {
  48. constructor(options) {
  49. super('Email already exists', options)
  50. }
  51. }
  52. class InvalidError extends BackwardCompatibleError {}
  53. class NotInV2Error extends BackwardCompatibleError {}
  54. class SLInV2Error extends BackwardCompatibleError {}
  55. class SAMLCommonsUnavailable extends OError {
  56. get i18nKey() {
  57. return 'saml_commons_unavailable'
  58. }
  59. }
  60. class SAMLDomainCaptureError extends OError {}
  61. class SAMLDomainCaptureMissingSessionDataError extends SAMLDomainCaptureError {}
  62. class SAMLDomainCaptureJoiningError extends SAMLDomainCaptureError {}
  63. class SAMLDomainCaptureEmailExistsError extends SAMLDomainCaptureJoiningError {
  64. get i18nKey() {
  65. return 'saml_email_on_another_account_error'
  66. }
  67. }
  68. class SAMLIdentityExistsError extends OError {
  69. get i18nKey() {
  70. return 'institution_account_tried_to_add_already_registered'
  71. }
  72. }
  73. class SAMLAlreadyLinkedError extends OError {
  74. get i18nKey() {
  75. return 'institution_account_tried_to_add_already_linked'
  76. }
  77. }
  78. class SAMLEmailNotAffiliatedError extends OError {
  79. get i18nKey() {
  80. return 'institution_account_tried_to_add_not_affiliated_2'
  81. }
  82. }
  83. class SAMLEmailAffiliatedWithAnotherInstitutionError extends OError {
  84. get i18nKey() {
  85. return 'institution_account_tried_to_add_affiliated_with_another_institution_2'
  86. }
  87. }
  88. class SAMLAuthenticationError extends OError {
  89. get i18nKey() {
  90. return 'saml_auth_error'
  91. }
  92. }
  93. class SAMLAssertionAudienceMismatch extends SAMLAuthenticationError {}
  94. class SAMLAuthenticationRequiredError extends SAMLAuthenticationError {
  95. get i18nKey() {
  96. return 'saml_authentication_required_error'
  97. }
  98. }
  99. class SAMLGroupSSOLoginIdentityMismatchError extends SAMLAuthenticationError {
  100. get i18nKey() {
  101. return 'saml_login_identity_mismatch_error'
  102. }
  103. }
  104. class SAMLGroupSSOLoginRequestedEmailNotConfirmed extends SAMLAuthenticationError {
  105. get i18nKey() {
  106. return 'saml_login_requested_email_not_confirmed_error'
  107. }
  108. }
  109. class SAMLGroupSSOLoginIdentityNotFoundError extends SAMLAuthenticationError {
  110. get i18nKey() {
  111. return 'saml_login_identity_not_found_error'
  112. }
  113. }
  114. class SAMLGroupSSODisabledError extends SAMLAuthenticationError {
  115. get i18nKey() {
  116. return 'saml_login_disabled_error'
  117. }
  118. }
  119. class SAMLInvalidSignatureError extends SAMLAuthenticationError {
  120. get i18nKey() {
  121. return 'saml_invalid_signature_error'
  122. }
  123. }
  124. class SAMLMissingSignatureError extends SAMLAuthenticationError {
  125. get i18nKey() {
  126. return 'saml_missing_signature_error'
  127. }
  128. }
  129. class SAMLInvalidUserIdentifierError extends SAMLAuthenticationError {
  130. get i18nKey() {
  131. return 'saml_authentication_required_error'
  132. }
  133. }
  134. class SAMLInvalidUserAttributeError extends SAMLAuthenticationError {
  135. get i18nKey() {
  136. return 'saml_authentication_required_error'
  137. }
  138. }
  139. class SAMLMissingUserIdentifierError extends SAMLAuthenticationError {
  140. get i18nKey() {
  141. return 'saml_missing_user_attribute'
  142. }
  143. }
  144. class SAMLInvalidResponseError extends SAMLAuthenticationError {}
  145. class SAMLResponseAlreadyProcessedError extends SAMLInvalidResponseError {
  146. constructor() {
  147. super('saml response already processed')
  148. }
  149. }
  150. class SAMLLoginFailureError extends SAMLAuthenticationError {
  151. get i18nKey() {
  152. return 'saml_login_failure'
  153. }
  154. }
  155. class SAMLEmailNotRecognizedError extends SAMLAuthenticationError {
  156. get i18nKey() {
  157. return 'saml_email_not_recognized'
  158. }
  159. }
  160. class SAMLDomainCaptureRegisterError extends SAMLAuthenticationError {}
  161. class SAMLRequestDeniedError extends SAMLAuthenticationError {
  162. get i18nKey() {
  163. return 'saml_request_denied_error'
  164. }
  165. }
  166. class SAMLDomainCaptureManagedUserOptInRequiredError extends OError {
  167. // use OError instead of SAMLDomainCaptureError since SAMLMiddleware will check for
  168. // SAMLDomainCaptureError and update SAML audit log but these errors do not need to be logged
  169. }
  170. class SAMLDomainCaptureManagedUserMissingEmailError extends OError {}
  171. class SAMLGroupMemberLimitReachedError extends OError {}
  172. class SAMLDomainCaptureManagedOptInUserMissingEmailError extends SAMLDomainCaptureError {}
  173. class SAMLSessionProviderDataMissing extends SAMLAuthenticationError {
  174. get i18nKey() {
  175. return 'try_again'
  176. }
  177. }
  178. class SAMLDomainCaptureEmailDomainMismatchError extends SAMLDomainCaptureError {
  179. get i18nKey() {
  180. return 'invalid_organization_email'
  181. }
  182. }
  183. class SAMLSessionDataMissing extends BackwardCompatibleError {
  184. constructor(arg) {
  185. super(arg)
  186. const samlSession =
  187. typeof arg === 'object' && arg !== null && arg.samlSession
  188. ? arg.samlSession
  189. : {}
  190. this.tryAgain = true
  191. const { universityId, universityName, externalUserId, institutionEmail } =
  192. samlSession
  193. if (
  194. !universityId &&
  195. !universityName &&
  196. !externalUserId &&
  197. !institutionEmail
  198. ) {
  199. this.message = 'Missing session data.'
  200. } else if (
  201. !institutionEmail &&
  202. samlSession &&
  203. samlSession.userEmailAttributeUnreliable
  204. ) {
  205. this.tryAgain = false
  206. this.message = `Your account settings at your institution prevent us from accessing your email address. You will need to make your email address public at your institution in order to link with ${settings.appName}. Please contact your IT department if you have any questions.`
  207. } else if (!institutionEmail) {
  208. this.message =
  209. 'Unable to confirm your institutional email address. The institutional identity provider did not provide an email address in the expected attribute. Please contact us if this keeps happening.'
  210. }
  211. }
  212. }
  213. class SAMLProviderRequesterError extends SAMLAuthenticationError {}
  214. class SAMLProviderRequesterInvalidNameIDPolicyError extends SAMLProviderRequesterError {
  215. get i18nKey() {
  216. return 'sso_provider_error_invalid_name'
  217. }
  218. }
  219. class ThirdPartyIdentityExistsError extends BackwardCompatibleError {
  220. constructor(arg) {
  221. super(arg)
  222. if (!this.message) {
  223. this.message =
  224. 'provider and external id already linked to another account'
  225. }
  226. }
  227. }
  228. class ThirdPartyUserNotFoundError extends BackwardCompatibleError {
  229. constructor(arg) {
  230. super(arg)
  231. if (!this.message) {
  232. this.message = 'user not found for provider and external id'
  233. }
  234. }
  235. }
  236. class OutputFileFetchFailedError extends OError {}
  237. class SubscriptionAdminDeletionError extends OErrorV2CompatibleError {
  238. constructor(options) {
  239. super('subscription admins cannot be deleted', options)
  240. }
  241. }
  242. class SubscriptionNotFoundError extends OErrorV2CompatibleError {
  243. constructor(options) {
  244. super('subscription not found', options)
  245. }
  246. }
  247. class ProjectNotFoundError extends OErrorV2CompatibleError {
  248. constructor(options) {
  249. super('project not found', options)
  250. }
  251. }
  252. class UserNotFoundError extends OErrorV2CompatibleError {
  253. constructor(options) {
  254. super('user not found', options)
  255. }
  256. }
  257. class UserNotCollaboratorError extends OErrorV2CompatibleError {
  258. constructor(options) {
  259. super('user not a collaborator', options)
  260. }
  261. }
  262. class DocHasRangesError extends OErrorV2CompatibleError {
  263. constructor(options) {
  264. super('document has ranges', options)
  265. }
  266. }
  267. class InvalidQueryError extends OErrorV2CompatibleError {
  268. constructor(options) {
  269. super('invalid search query', options)
  270. }
  271. }
  272. class AffiliationError extends OError {}
  273. class InvalidEmailError extends OError {
  274. get i18nKey() {
  275. return 'invalid_email'
  276. }
  277. }
  278. class InvalidInstitutionalEmailError extends OError {
  279. get i18nKey() {
  280. return 'invalid_institutional_email'
  281. }
  282. }
  283. class NonDeletableEntityError extends OError {
  284. get i18nKey() {
  285. return 'non_deletable_entity'
  286. }
  287. }
  288. class FoundConnectedClientsError extends OError {
  289. constructor(nConnectedClients) {
  290. super(`found ${nConnectedClients} remaining connected clients`)
  291. }
  292. }
  293. class ConcurrentLoadingOfDocsDetectedError extends OError {
  294. constructor() {
  295. super('concurrent loading of docs detected')
  296. }
  297. }
  298. class DomainAlreadyExistsError extends OErrorV2CompatibleError {}
  299. module.exports = {
  300. OError,
  301. BackwardCompatibleError,
  302. NotFoundError,
  303. ForbiddenError,
  304. ServiceNotConfiguredError,
  305. TooManyRequestsError,
  306. ResourceGoneError,
  307. DuplicateNameError,
  308. InvalidNameError,
  309. UnsupportedFileTypeError,
  310. FileTooLargeError,
  311. UnsupportedExportRecordsError,
  312. V1HistoryNotSyncedError,
  313. ProjectHistoryDisabledError,
  314. V1ConnectionError,
  315. UnconfirmedEmailError,
  316. EmailExistsError,
  317. InvalidError,
  318. NotInV2Error,
  319. OutputFileFetchFailedError,
  320. SAMLAssertionAudienceMismatch,
  321. SAMLAuthenticationRequiredError,
  322. SAMLCommonsUnavailable,
  323. SAMLDomainCaptureEmailExistsError,
  324. SAMLDomainCaptureEmailDomainMismatchError,
  325. SAMLDomainCaptureError,
  326. SAMLDomainCaptureJoiningError,
  327. SAMLDomainCaptureMissingSessionDataError,
  328. SAMLIdentityExistsError,
  329. SAMLAlreadyLinkedError,
  330. SAMLEmailNotAffiliatedError,
  331. SAMLEmailAffiliatedWithAnotherInstitutionError,
  332. SAMLSessionDataMissing,
  333. SAMLSessionProviderDataMissing,
  334. SAMLAuthenticationError,
  335. SAMLGroupSSOLoginIdentityMismatchError,
  336. SAMLGroupSSOLoginIdentityNotFoundError,
  337. SAMLGroupSSODisabledError,
  338. SAMLGroupSSOLoginRequestedEmailNotConfirmed,
  339. SAMLInvalidUserAttributeError,
  340. SAMLInvalidUserIdentifierError,
  341. SAMLInvalidSignatureError,
  342. SAMLMissingUserIdentifierError,
  343. SAMLMissingSignatureError,
  344. SAMLProviderRequesterError,
  345. SAMLProviderRequesterInvalidNameIDPolicyError,
  346. SAMLInvalidResponseError,
  347. SAMLLoginFailureError,
  348. SAMLEmailNotRecognizedError,
  349. SAMLResponseAlreadyProcessedError,
  350. SAMLRequestDeniedError,
  351. SAMLDomainCaptureRegisterError,
  352. SAMLDomainCaptureManagedUserMissingEmailError,
  353. SAMLGroupMemberLimitReachedError,
  354. SAMLDomainCaptureManagedUserOptInRequiredError,
  355. SAMLDomainCaptureManagedOptInUserMissingEmailError,
  356. SLInV2Error,
  357. ThirdPartyIdentityExistsError,
  358. ThirdPartyUserNotFoundError,
  359. SubscriptionAdminDeletionError,
  360. SubscriptionNotFoundError,
  361. ProjectNotFoundError,
  362. UserNotFoundError,
  363. UserNotCollaboratorError,
  364. DocHasRangesError,
  365. InvalidQueryError,
  366. AffiliationError,
  367. InvalidEmailError,
  368. InvalidInstitutionalEmailError,
  369. NonDeletableEntityError,
  370. FoundConnectedClientsError,
  371. ConcurrentLoadingOfDocsDetectedError,
  372. DomainAlreadyExistsError,
  373. }