User.coffee 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. request = require("./request")
  2. _ = require("underscore")
  3. settings = require("settings-sharelatex")
  4. {db, ObjectId} = require("../../../../app/js/infrastructure/mongojs")
  5. UserModel = require("../../../../app/js/models/User").User
  6. UserUpdater = require("../../../../app/js/Features/User/UserUpdater")
  7. AuthenticationManager = require("../../../../app/js/Features/Authentication/AuthenticationManager")
  8. count = 0
  9. class User
  10. constructor: (options = {}) ->
  11. @emails = [
  12. email: "acceptance-test-#{count}@example.com"
  13. createdAt: new Date()
  14. ]
  15. @email = @emails[0].email
  16. @password = "acceptance-test-#{count}-password"
  17. count++
  18. @jar = request.jar()
  19. @request = request.defaults({
  20. jar: @jar
  21. })
  22. setExtraAttributes: (user) ->
  23. throw new Error("User does not exist") unless user?._id?
  24. @id = user._id.toString()
  25. @_id = user._id.toString()
  26. @first_name = user.first_name
  27. @referal_id = user.referal_id
  28. get: (callback = (error, user)->) ->
  29. db.users.findOne { _id: ObjectId(@_id) }, callback
  30. mongoUpdate: (updateOp, callback=(error)->) ->
  31. db.users.update {_id: ObjectId(@_id)}, updateOp, callback
  32. register: (callback = (error, user) ->) ->
  33. @registerWithQuery('', callback)
  34. registerWithQuery: (query, callback = (error, user) ->) ->
  35. return callback(new Error('User already registered')) if @_id?
  36. @getCsrfToken (error) =>
  37. return callback(error) if error?
  38. @request.post {
  39. url: '/register' + query
  40. json: { @email, @password }
  41. }, (error, response, body) =>
  42. return callback(error) if error?
  43. db.users.findOne { email: @email }, (error, user) =>
  44. return callback(error) if error?
  45. @setExtraAttributes user
  46. callback(null, user)
  47. login: (callback = (error) ->) ->
  48. @loginWith(@email, callback)
  49. loginWith: (email, callback = (error) ->) ->
  50. @ensureUserExists (error) =>
  51. return callback(error) if error?
  52. @getCsrfToken (error) =>
  53. return callback(error) if error?
  54. @request.post {
  55. url: if settings.enableLegacyLogin then "/login/legacy" else "/login"
  56. json: { email, @password }
  57. }, callback
  58. ensureUserExists: (callback = (error) ->) ->
  59. filter = {@email}
  60. options = {upsert: true, new: true, setDefaultsOnInsert: true}
  61. UserModel.findOneAndUpdate filter, {}, options, (error, user) =>
  62. return callback(error) if error?
  63. AuthenticationManager.setUserPassword user._id, @password, (error) =>
  64. return callback(error) if error?
  65. UserUpdater.updateUser user._id, $set: emails: @emails, (error) =>
  66. return callback(error) if error?
  67. @setExtraAttributes user
  68. callback(null, @password)
  69. setFeatures: (features, callback = (error) ->) ->
  70. update = {}
  71. for key, value of features
  72. update["features.#{key}"] = value
  73. UserModel.update { _id: @id }, update, callback
  74. setOverleafId: (overleaf_id, callback = (error) ->) ->
  75. UserModel.update { _id: @id }, { 'overleaf.id': overleaf_id }, callback
  76. logout: (callback = (error) ->) ->
  77. @getCsrfToken (error) =>
  78. return callback(error) if error?
  79. @request.get {
  80. url: "/logout"
  81. json:
  82. email: @email
  83. password: @password
  84. }, (error, response, body) =>
  85. return callback(error) if error?
  86. db.users.findOne {email: @email}, (error, user) =>
  87. return callback(error) if error?
  88. @id = user?._id?.toString()
  89. @_id = user?._id?.toString()
  90. callback()
  91. addEmail: (email, callback = (error) ->) ->
  92. @emails.push(email: email, createdAt: new Date())
  93. UserUpdater.addEmailAddress @id, email, callback
  94. confirmEmail: (email, callback = (error) ->) ->
  95. for emailData, idx in @emails
  96. @emails[idx].confirmedAt = new Date() if emailData.email == email
  97. UserUpdater.confirmEmail @id, email, callback
  98. ensure_admin: (callback = (error) ->) ->
  99. db.users.update {_id: ObjectId(@id)}, { $set: { isAdmin: true }}, callback
  100. upgradeFeatures: (callback = (error) -> ) ->
  101. features = {
  102. collaborators: -1 # Infinite
  103. versioning: true
  104. dropbox:true
  105. compileTimeout: 60
  106. compileGroup:"priority"
  107. templates: true
  108. references: true
  109. trackChanges: true
  110. trackChangesVisible: true
  111. }
  112. db.users.update {_id: ObjectId(@id)}, { $set: { features: features }}, callback
  113. downgradeFeatures: (callback = (error) -> ) ->
  114. features = {
  115. collaborators: 1
  116. versioning: false
  117. dropbox:false
  118. compileTimeout: 60
  119. compileGroup:"standard"
  120. templates: false
  121. references: false
  122. trackChanges: false
  123. trackChangesVisible: false
  124. }
  125. db.users.update {_id: ObjectId(@id)}, { $set: { features: features }}, callback
  126. defaultFeatures: (callback = (error) -> ) ->
  127. features = settings.defaultFeatures
  128. db.users.update {_id: ObjectId(@id)}, { $set: { features: features }}, callback
  129. full_delete_user: (email, callback = (error) ->) ->
  130. db.users.findOne {email: email}, (error, user) =>
  131. if !user?
  132. return callback()
  133. user_id = user._id
  134. db.projects.remove owner_ref:ObjectId(user_id), {multi:true}, (err)->
  135. if err?
  136. callback(err)
  137. db.users.remove {_id: ObjectId(user_id)}, callback
  138. getProject: (project_id, callback = (error, project)->) ->
  139. db.projects.findOne {_id: ObjectId(project_id.toString())}, callback
  140. saveProject: (project, callback=(error)->) ->
  141. db.projects.update {_id: project._id}, project, callback
  142. createProject: (name, options, callback = (error, oroject_id) ->) ->
  143. if typeof options == "function"
  144. callback = options
  145. options = {}
  146. @request.post {
  147. url: "/project/new",
  148. json: Object.assign({projectName: name}, options)
  149. }, (error, response, body) ->
  150. return callback(error) if error?
  151. if !body?.project_id?
  152. error = new Error("SOMETHING WENT WRONG CREATING PROJECT", response.statusCode, response.headers["location"], body)
  153. callback error
  154. else
  155. callback(null, body.project_id)
  156. deleteProject: (project_id, callback=(error)) ->
  157. @request.delete {
  158. url: "/project/#{project_id}"
  159. }, (error, response, body) ->
  160. return callback(error) if error?
  161. callback(null)
  162. deleteProjects: (callback=(error)) ->
  163. db.projects.remove owner_ref:ObjectId(@id), {multi:true}, (err)->
  164. callback(err)
  165. openProject: (project_id, callback=(error)) ->
  166. @request.get {
  167. url: "/project/#{project_id}"
  168. }, (error, response, body) ->
  169. return callback(error) if error?
  170. if response.statusCode != 200
  171. err = new Error("Non-success response when opening project: #{response.statusCode}")
  172. return callback(err)
  173. callback(null)
  174. createDocInProject: (project_id, parent_folder_id, name, callback=(error, doc_id)->) ->
  175. @getCsrfToken (error) =>
  176. return callback(error) if error?
  177. @request.post {
  178. url: "/project/#{project_id}/doc",
  179. json: {
  180. name: name,
  181. parent_folder_id: parent_folder_id
  182. }
  183. }, (error, response, body) =>
  184. callback(null, body._id)
  185. addUserToProject: (project_id, user, privileges, callback = (error, user) ->) ->
  186. if privileges == 'readAndWrite'
  187. updateOp = {$addToSet: {collaberator_refs: user._id.toString()}}
  188. else if privileges == 'readOnly'
  189. updateOp = {$addToSet: {readOnly_refs: user._id.toString()}}
  190. db.projects.update {_id: db.ObjectId(project_id)}, updateOp, (err) ->
  191. callback(err)
  192. makePublic: (project_id, level, callback = (error) ->) ->
  193. @request.post {
  194. url: "/project/#{project_id}/settings/admin",
  195. json:
  196. publicAccessLevel: level
  197. }, (error, response, body) ->
  198. return callback(error) if error?
  199. callback(null)
  200. makePrivate: (project_id, callback = (error) ->) ->
  201. @request.post {
  202. url: "/project/#{project_id}/settings/admin",
  203. json:
  204. publicAccessLevel: 'private'
  205. }, (error, response, body) ->
  206. return callback(error) if error?
  207. callback(null)
  208. makeTokenBased: (project_id, callback = (error) ->) ->
  209. @request.post {
  210. url: "/project/#{project_id}/settings/admin",
  211. json:
  212. publicAccessLevel: 'tokenBased'
  213. }, (error, response, body) ->
  214. return callback(error) if error?
  215. callback(null)
  216. getCsrfToken: (callback = (error) ->) ->
  217. @request.get {
  218. url: "/dev/csrf"
  219. }, (err, response, body) =>
  220. return callback(err) if err?
  221. @csrfToken = body
  222. @request = @request.defaults({
  223. headers:
  224. "x-csrf-token": @csrfToken
  225. })
  226. callback()
  227. changePassword: (callback = (error) ->) ->
  228. @getCsrfToken (error) =>
  229. return callback(error) if error?
  230. @request.post {
  231. url: "/user/password/update"
  232. json:
  233. currentPassword: @password
  234. newPassword1: @password
  235. newPassword2: @password
  236. }, (error, response, body) =>
  237. return callback(error) if error?
  238. db.users.findOne {email: @email}, (error, user) =>
  239. return callback(error) if error?
  240. callback()
  241. getUserSettingsPage: (callback = (error, statusCode) ->) ->
  242. @getCsrfToken (error) =>
  243. return callback(error) if error?
  244. @request.get {
  245. url: "/user/settings"
  246. }, (error, response, body) =>
  247. return callback(error) if error?
  248. callback(null, response.statusCode)
  249. activateSudoMode: (callback = (error)->) ->
  250. @getCsrfToken (error) =>
  251. return callback(error) if error?
  252. @request.post {
  253. uri: '/confirm-password',
  254. json:
  255. password: @password
  256. }, callback
  257. updateSettings: (newSettings, callback = (error, response, body) ->) ->
  258. @getCsrfToken (error) =>
  259. return callback(error) if error?
  260. @request.post {
  261. url: '/user/settings'
  262. json: newSettings
  263. }, callback
  264. getProjectListPage: (callback=(error, statusCode)->) ->
  265. @getCsrfToken (error) =>
  266. return callback(error) if error?
  267. @request.get {
  268. url: "/project"
  269. }, (error, response, body) =>
  270. return callback(error) if error?
  271. callback(null, response.statusCode)
  272. isLoggedIn: (callback = (error, loggedIn) ->) ->
  273. @request.get "/user/personal_info", (error, response, body) ->
  274. return callback(error) if error?
  275. if response.statusCode == 200
  276. return callback(null, true)
  277. else if response.statusCode == 302
  278. return callback(null, false)
  279. else
  280. return callback(new Error("unexpected status code from /user/personal_info: #{response.statusCode}"))
  281. module.exports = User