User.coffee 9.5 KB

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