WebApiManager.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { callbackifyMultiResult } from '@overleaf/promise-utils'
  2. import OError from '@overleaf/o-error'
  3. import settings from '@overleaf/settings'
  4. import logger from '@overleaf/logger'
  5. import Errors from './Errors.js'
  6. import Path from 'node:path'
  7. import { fetchJson, RequestFailedError } from '@overleaf/fetch-utils'
  8. const {
  9. CodedError,
  10. CorruptedJoinProjectResponseError,
  11. NotAuthorizedError,
  12. WebApiRequestFailedError,
  13. } = Errors
  14. async function joinProject(projectId, user) {
  15. const userId = user._id
  16. logger.debug({ projectId, userId }, 'sending join project request to web')
  17. const url = new URL(settings.apis.web.url)
  18. url.pathname = Path.posix.join('project', projectId, 'join')
  19. let data
  20. try {
  21. data = await fetchJson(url, {
  22. method: 'POST',
  23. basicAuth: {
  24. user: settings.apis.web.user,
  25. password: settings.apis.web.pass,
  26. },
  27. json: {
  28. userId,
  29. anonymousAccessToken: user.anonymousAccessToken,
  30. },
  31. })
  32. } catch (error) {
  33. if (error instanceof RequestFailedError) {
  34. if (error.response.status === 429) {
  35. throw new CodedError(
  36. 'rate-limit hit when joining project',
  37. 'TooManyRequests'
  38. )
  39. } else if (error.response.status === 403) {
  40. throw new NotAuthorizedError()
  41. } else if (error.response.status === 404) {
  42. throw new CodedError('project not found', 'ProjectNotFound')
  43. }
  44. throw new WebApiRequestFailedError(error.response.status)
  45. }
  46. throw OError.tag(error, 'join project request failed')
  47. }
  48. if (!(data && data.project)) {
  49. throw new CorruptedJoinProjectResponseError()
  50. }
  51. const userMetadata = {
  52. isRestrictedUser: data.isRestrictedUser,
  53. isTokenMember: data.isTokenMember,
  54. isInvitedMember: data.isInvitedMember,
  55. }
  56. return {
  57. project: data.project,
  58. privilegeLevel: data.privilegeLevel,
  59. userMetadata,
  60. }
  61. }
  62. export default {
  63. joinProject: callbackifyMultiResult(joinProject, [
  64. 'project',
  65. 'privilegeLevel',
  66. 'userMetadata',
  67. ]),
  68. promises: {
  69. joinProject,
  70. },
  71. }