User.coffee 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. openProject: (project_id, callback=(error)) ->
  163. @request.get {
  164. url: "/project/#{project_id}"
  165. }, (error, response, body) ->
  166. return callback(error) if error?
  167. if response.statusCode != 200
  168. err = new Error("Non-success response when opening project: #{response.statusCode}")
  169. return callback(err)
  170. callback(null)
  171. createDocInProject: (project_id, parent_folder_id, name, callback=(error, doc_id)->) ->
  172. @getCsrfToken (error) =>
  173. return callback(error) if error?
  174. @request.post {
  175. url: "/project/#{project_id}/doc",
  176. json: {
  177. name: name,
  178. parent_folder_id: parent_folder_id
  179. }
  180. }, (error, response, body) =>
  181. callback(null, body._id)
  182. addUserToProject: (project_id, user, privileges, callback = (error, user) ->) ->
  183. if privileges == 'readAndWrite'
  184. updateOp = {$addToSet: {collaberator_refs: user._id.toString()}}
  185. else if privileges == 'readOnly'
  186. updateOp = {$addToSet: {readOnly_refs: user._id.toString()}}
  187. db.projects.update {_id: db.ObjectId(project_id)}, updateOp, (err) ->
  188. callback(err)
  189. makePublic: (project_id, level, callback = (error) ->) ->
  190. @request.post {
  191. url: "/project/#{project_id}/settings/admin",
  192. json:
  193. publicAccessLevel: level
  194. }, (error, response, body) ->
  195. return callback(error) if error?
  196. callback(null)
  197. makePrivate: (project_id, callback = (error) ->) ->
  198. @request.post {
  199. url: "/project/#{project_id}/settings/admin",
  200. json:
  201. publicAccessLevel: 'private'
  202. }, (error, response, body) ->
  203. return callback(error) if error?
  204. callback(null)
  205. makeTokenBased: (project_id, callback = (error) ->) ->
  206. @request.post {
  207. url: "/project/#{project_id}/settings/admin",
  208. json:
  209. publicAccessLevel: 'tokenBased'
  210. }, (error, response, body) ->
  211. return callback(error) if error?
  212. callback(null)
  213. getCsrfToken: (callback = (error) ->) ->
  214. @request.get {
  215. url: "/dev/csrf"
  216. }, (err, response, body) =>
  217. return callback(err) if err?
  218. @csrfToken = body
  219. @request = @request.defaults({
  220. headers:
  221. "x-csrf-token": @csrfToken
  222. })
  223. callback()
  224. changePassword: (callback = (error) ->) ->
  225. @getCsrfToken (error) =>
  226. return callback(error) if error?
  227. @request.post {
  228. url: "/user/password/update"
  229. json:
  230. currentPassword: @password
  231. newPassword1: @password
  232. newPassword2: @password
  233. }, (error, response, body) =>
  234. return callback(error) if error?
  235. db.users.findOne {email: @email}, (error, user) =>
  236. return callback(error) if error?
  237. callback()
  238. getUserSettingsPage: (callback = (error, statusCode) ->) ->
  239. @getCsrfToken (error) =>
  240. return callback(error) if error?
  241. @request.get {
  242. url: "/user/settings"
  243. }, (error, response, body) =>
  244. return callback(error) if error?
  245. callback(null, response.statusCode)
  246. activateSudoMode: (callback = (error)->) ->
  247. @getCsrfToken (error) =>
  248. return callback(error) if error?
  249. @request.post {
  250. uri: '/confirm-password',
  251. json:
  252. password: @password
  253. }, callback
  254. updateSettings: (newSettings, callback = (error, response, body) ->) ->
  255. @getCsrfToken (error) =>
  256. return callback(error) if error?
  257. @request.post {
  258. url: '/user/settings'
  259. json: newSettings
  260. }, callback
  261. getProjectListPage: (callback=(error, statusCode)->) ->
  262. @getCsrfToken (error) =>
  263. return callback(error) if error?
  264. @request.get {
  265. url: "/project"
  266. }, (error, response, body) =>
  267. return callback(error) if error?
  268. callback(null, response.statusCode)
  269. isLoggedIn: (callback = (error, loggedIn) ->) ->
  270. @request.get "/user/personal_info", (error, response, body) ->
  271. return callback(error) if error?
  272. if response.statusCode == 200
  273. return callback(null, true)
  274. else if response.statusCode == 302
  275. return callback(null, false)
  276. else
  277. return callback(new Error("unexpected status code from /user/personal_info: #{response.statusCode}"))
  278. module.exports = User