TokenAccessHandler.coffee 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. Project = require('../../models/Project').Project
  2. CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
  3. PublicAccessLevels = require '../Authorization/PublicAccessLevels'
  4. PrivilegeLevels = require '../Authorization/PrivilegeLevels'
  5. UserGetter = require '../User/UserGetter'
  6. ObjectId = require("mongojs").ObjectId
  7. Settings = require('settings-sharelatex')
  8. V1Api = require "../V1/V1Api"
  9. module.exports = TokenAccessHandler =
  10. ANONYMOUS_READ_AND_WRITE_ENABLED:
  11. Settings.allowAnonymousReadAndWriteSharing == true
  12. findProjectWithReadOnlyToken: (token, callback=(err, project, projectExists)->) ->
  13. Project.findOne {
  14. 'tokens.readOnly': token
  15. }, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, (err, project) ->
  16. if err?
  17. return callback(err)
  18. if !project?
  19. return callback(null, null, false) # Project doesn't exist, so we handle differently
  20. if project.publicAccesLevel != PublicAccessLevels.TOKEN_BASED
  21. return callback(null, null, true) # Project does exist, but it isn't token based
  22. return callback(null, project, true)
  23. findProjectWithReadAndWriteToken: (token, callback=(err, project, projectExists)->) ->
  24. Project.findOne {
  25. 'tokens.readAndWrite': token
  26. }, {_id: 1, publicAccesLevel: 1, owner_ref: 1}, (err, project) ->
  27. if err?
  28. return callback(err)
  29. if !project?
  30. return callback(null, null, false) # Project doesn't exist, so we handle differently
  31. if project.publicAccesLevel != PublicAccessLevels.TOKEN_BASED
  32. return callback(null, null, true) # Project does exist, but it isn't token based
  33. return callback(null, project, true)
  34. findProjectWithHigherAccess: (token, userId, callback=(err, project)->) ->
  35. Project.findOne {
  36. $or: [
  37. {'tokens.readAndWrite': token},
  38. {'tokens.readOnly': token}
  39. ]
  40. }, {_id: 1}, (err, project) ->
  41. if err?
  42. return callback(err)
  43. if !project?
  44. return callback(null, null)
  45. projectId = project._id
  46. CollaboratorsHandler.isUserInvitedMemberOfProject userId, projectId, (err, isMember) ->
  47. if err?
  48. return callback(err)
  49. callback(
  50. null,
  51. if isMember == true then project else null
  52. )
  53. addReadOnlyUserToProject: (userId, projectId, callback=(err)->) ->
  54. userId = ObjectId(userId.toString())
  55. projectId = ObjectId(projectId.toString())
  56. Project.update {
  57. _id: projectId
  58. }, {
  59. $addToSet: {tokenAccessReadOnly_refs: userId}
  60. }, callback
  61. addReadAndWriteUserToProject: (userId, projectId, callback=(err)->) ->
  62. userId = ObjectId(userId.toString())
  63. projectId = ObjectId(projectId.toString())
  64. Project.update {
  65. _id: projectId
  66. }, {
  67. $addToSet: {tokenAccessReadAndWrite_refs: userId}
  68. }, callback
  69. grantSessionTokenAccess: (req, projectId, token) ->
  70. if req.session?
  71. if !req.session.anonTokenAccess?
  72. req.session.anonTokenAccess = {}
  73. req.session.anonTokenAccess[projectId.toString()] = token.toString()
  74. getRequestToken: (req, projectId) ->
  75. token = (
  76. req?.session?.anonTokenAccess?[projectId.toString()] or
  77. req?.headers['x-sl-anonymous-access-token']
  78. )
  79. return token
  80. isValidToken: (projectId, token, callback=(err, isValidReadAndWrite, isValidReadOnly)->) ->
  81. if !token
  82. return callback null, false, false
  83. _validate = (project) ->
  84. project? and
  85. project.publicAccesLevel == PublicAccessLevels.TOKEN_BASED and
  86. project._id.toString() == projectId.toString()
  87. TokenAccessHandler.findProjectWithReadAndWriteToken token, (err, readAndWriteProject) ->
  88. return callback(err) if err?
  89. isValidReadAndWrite = _validate(readAndWriteProject)
  90. TokenAccessHandler.findProjectWithReadOnlyToken token, (err, readOnlyProject) ->
  91. return callback(err) if err?
  92. isValidReadOnly = _validate(readOnlyProject)
  93. callback null, isValidReadAndWrite, isValidReadOnly
  94. protectTokens: (project, privilegeLevel) ->
  95. if project? && project.tokens?
  96. if privilegeLevel == PrivilegeLevels.OWNER
  97. return
  98. if privilegeLevel != PrivilegeLevels.READ_AND_WRITE
  99. project.tokens.readAndWrite = ''
  100. if privilegeLevel != PrivilegeLevels.READ_ONLY
  101. project.tokens.readOnly = ''
  102. getV1DocPublishedInfo: (token, callback = (err, publishedInfo) ->) ->
  103. # default to allowing access
  104. return callback(null, {
  105. allow: true
  106. }) unless Settings.apis?.v1?
  107. V1Api.request { url: "/api/v1/sharelatex/docs/#{token}/is_published" }, (err, response, body) ->
  108. return callback err if err?
  109. callback null, body
  110. getV1DocInfo: (token, v2UserId, callback=(err, info)->) ->
  111. # default to not exported
  112. return callback(null, {
  113. exists: true
  114. exported: false
  115. }) unless Settings.apis?.v1?
  116. UserGetter.getUser v2UserId, { overleaf: 1 }, (err, user) ->
  117. return callback(err) if err?
  118. v1UserId = user.overleaf?.id
  119. V1Api.request { url: "/api/v1/sharelatex/users/#{v1UserId}/docs/#{token}/info" }, (err, response, body) ->
  120. return callback err if err?
  121. callback null, body
  122. module.exports.READ_AND_WRITE_TOKEN_REGEX = /^(\d+)(\w+)$/
  123. module.exports.READ_AND_WRITE_URL_REGEX = /^\/(\d+)(\w+)$/
  124. module.exports.READ_ONLY_TOKEN_REGEX = /^([a-z]{12})$/
  125. module.exports.READ_ONLY_URL_REGEX = /^\/read\/([a-z]{12})$/