user.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. process.env.NODE_ENV = 'test'
  2. process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
  3. let chai = require('chai')
  4. let server = require('../server')
  5. let should = chai.should()
  6. let { sequelize } = require('../models')
  7. const Errors = require('../lib/errors.js')
  8. chai.use(require('chai-http'))
  9. chai.use(require('chai-things'))
  10. describe('User', () => {
  11. //Wait for app to start before commencing
  12. before((done) => {
  13. if(server.locals.appStarted) done()
  14. server.on('appStarted', () => {
  15. done()
  16. })
  17. })
  18. //Delete all rows in table after
  19. //tests completed
  20. after(() => sequelize.sync({ force: true }) )
  21. describe('/ POST user', () => {
  22. it('should create an account', (done) => {
  23. chai.request(server)
  24. .post('/api/v1/user')
  25. .set('content-type', 'application/x-www-form-urlencoded')
  26. .send({
  27. username: 'username',
  28. password: 'password'
  29. })
  30. .end((err, res) => {
  31. res.should.have.status(200)
  32. res.should.be.json
  33. res.body.should.have.property('username', 'username')
  34. res.body.should.have.property('hash')
  35. done()
  36. })
  37. })
  38. it('should create an admin account if no is already created', (done) => {
  39. chai.request(server)
  40. .post('/api/v1/user')
  41. .set('content-type', 'application/json')
  42. .send({
  43. username: 'adminaccount',
  44. password: 'password',
  45. admin: true
  46. })
  47. .end((err, res) => {
  48. res.should.have.status(200)
  49. res.body.should.have.property('username', 'adminaccount')
  50. res.body.should.have.property('hash')
  51. res.body.should.have.property('admin', true)
  52. done()
  53. })
  54. })
  55. it('should give an error if an admin account is already created and no token is provided', (done) => {
  56. chai.request(server)
  57. .post('/api/v1/user')
  58. .set('content-type', 'application/json')
  59. .send({
  60. username: 'adminaccount1',
  61. password: 'password',
  62. admin: true
  63. })
  64. .end((err, res) => {
  65. res.should.have.status(400)
  66. res.should.be.json
  67. res.body.should.have.property('errors')
  68. res.body.errors.should.include.something.that.deep.equals(Errors.missingParameter('token'))
  69. done()
  70. })
  71. })
  72. it('should give an error if admin and token fields are not of the correct type ', (done) => {
  73. chai.request(server)
  74. .post('/api/v1/user')
  75. .set('content-type', 'application/json')
  76. .send({
  77. username: 'adminaccount1',
  78. password: 'password',
  79. admin: 'not a boolean',
  80. token: 123
  81. })
  82. .end((err, res) => {
  83. res.should.have.status(400)
  84. res.should.be.json
  85. res.body.should.have.property('errors')
  86. res.body.errors.should.include.something.that.deep.equals(Errors.invalidParameterType('admin', 'boolean'))
  87. res.body.errors.should.include.something.that.deep.equals(Errors.invalidParameterType('token', 'string'))
  88. done()
  89. })
  90. })
  91. it('should give an error if an admin account is already created and token is invalid', (done) => {
  92. chai.request(server)
  93. .post('/api/v1/user')
  94. .set('content-type', 'application/json')
  95. .send({
  96. username: 'adminaccount1',
  97. password: 'password',
  98. admin: true,
  99. token: 'invalid_token'
  100. })
  101. .end((err, res) => {
  102. res.should.have.status(401)
  103. res.should.be.json
  104. res.body.should.have.property('errors')
  105. res.body.errors.should.include.something.that.deep.equals(Errors.invalidToken)
  106. done()
  107. })
  108. })
  109. it('should create an admin account provided with a token', async () => {
  110. let agent = chai.request.agent(server)
  111. await agent
  112. .post('/api/v1/user/adminaccount/login')
  113. .set('content-type', 'application/json')
  114. .send({
  115. password: 'password'
  116. })
  117. let tokenRes = await agent.post('/api/v1/admin_token')
  118. let token = tokenRes.body.token
  119. let accountRes = await chai.request(server)
  120. .post('/api/v1/user')
  121. .set('content-type', 'application/json')
  122. .send({
  123. username: 'adminaccount1',
  124. password: 'password',
  125. admin: true,
  126. token: token
  127. })
  128. accountRes.should.have.status(200)
  129. accountRes.should.be.json
  130. accountRes.body.should.have.property('admin', true)
  131. accountRes.body.should.have.property('username', 'adminaccount1')
  132. accountRes.body.should.have.property('hash')
  133. try {
  134. let invalidAccountRes = await chai.request(server)
  135. .post('/api/v1/user')
  136. .set('content-type', 'application/json')
  137. .send({
  138. username: 'adminaccount2',
  139. password: 'password',
  140. admin: true,
  141. token: token
  142. })
  143. invalidAccountRes.should.have.status(401)
  144. invalidAccountRes.should.be.json
  145. invalidAccountRes.body.should.have.property('errors')
  146. invalidAccountRes.body.errors.should.include.something.that.deep.equals(Errors.invalidToken)
  147. } catch (res) {
  148. res.should.have.status(401)
  149. JSON.parse(res.response.text).errors.should.include.something.that.deep.equals(Errors.invalidToken)
  150. }
  151. })
  152. it('should log in the user after creating an account', (done) => {
  153. let agent = chai.request.agent(server)
  154. agent
  155. .post('/api/v1/user')
  156. .set('content-type', 'application/x-www-form-urlencoded')
  157. .send({
  158. username: 'username1',
  159. password: 'password'
  160. })
  161. .end((err, res) => {
  162. agent
  163. .get('/api/v1/user/username1')
  164. .then((res) => {
  165. res.should.have.status(200)
  166. done()
  167. })
  168. .catch(done)
  169. })
  170. })
  171. it('should throw an error if account already created', (done) => {
  172. chai.request(server)
  173. .post('/api/v1/user')
  174. .set('content-type', 'application/x-www-form-urlencoded')
  175. .send({
  176. username: 'username',
  177. password: 'password'
  178. })
  179. .end((err, res) => {
  180. res.should.have.status(400)
  181. res.should.be.json
  182. res.body.should.have.property('errors')
  183. res.body.errors.should.include.something.that.deep.equals(Errors.accountAlreadyCreated)
  184. done()
  185. })
  186. })
  187. it('should throw an error if no username or password', (done) => {
  188. chai.request(server)
  189. .post('/api/v1/user')
  190. .set('content-type', 'application/x-www-form-urlencoded')
  191. .send({})
  192. .end((err, res) => {
  193. res.should.have.status(400)
  194. res.should.be.json
  195. res.body.should.have.property('errors')
  196. res.body.errors.should.include.something.that.deep.equals(Errors.missingParameter('username'))
  197. res.body.errors.should.include.something.that.deep.equals(Errors.missingParameter('password'))
  198. done()
  199. })
  200. })
  201. it('should throw an error if username or password are not a string', (done) => {
  202. chai.request(server)
  203. .post('/api/v1/user')
  204. .set('content-type', 'application/json')
  205. .send({
  206. username: 123,
  207. password: 123
  208. })
  209. .end((err, res) => {
  210. res.should.have.status(400)
  211. res.should.be.json
  212. res.body.should.have.property('errors')
  213. res.body.should.have.property('errors')
  214. res.body.errors.should.include.something.that.deep.equals(Errors.invalidParameterType('username', 'string'))
  215. res.body.errors.should.include.something.that.deep.equals(Errors.invalidParameterType('password', 'string'))
  216. done()
  217. })
  218. })
  219. it('should throw an error if username or password less than 6 characters', (done) => {
  220. chai.request(server)
  221. .post('/api/v1/user')
  222. .set('content-type', 'application/x-www-form-urlencoded')
  223. .send({
  224. username: 'test',
  225. password: 'pass'
  226. })
  227. .end((err, res) => {
  228. res.should.have.status(400)
  229. res.should.be.json
  230. res.body.should.have.property('errors')
  231. res.body.errors.should.contain.something.that.deep.equals(Errors.parameterLengthTooSmall('username', '6'))
  232. res.body.errors.should.contain.something.that.deep.equals(Errors.parameterLengthTooSmall('password', '6'))
  233. done()
  234. })
  235. })
  236. it('should throw an error if username greater than 50 characters or password is greater than 100 characters', (done) => {
  237. chai.request(server)
  238. .post('/api/v1/user')
  239. .set('content-type', 'application/x-www-form-urlencoded')
  240. .send({
  241. username: '123456789012345678901234567890123456789012345678901',
  242. password: '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901'
  243. })
  244. .end((err, res) => {
  245. res.should.have.status(400)
  246. res.should.be.json
  247. res.body.should.have.property('errors')
  248. res.body.errors.should.contain.something.that.deep.equals(Errors.parameterLengthTooLarge('username', '50'))
  249. res.body.errors.should.contain.something.that.deep.equals(Errors.parameterLengthTooLarge('password', '100'))
  250. done()
  251. })
  252. })
  253. })
  254. describe('/:username/login POST user', () => {
  255. let agent = chai.request.agent(server)
  256. it('should throw an error if invalid username is provided', (done) => {
  257. chai.request(server)
  258. .post('/api/v1/user/invalid_username/login')
  259. .set('content-type', 'application/x-www-form-urlencoded')
  260. .send({
  261. password: 'password'
  262. })
  263. .end((err, res) => {
  264. res.should.have.status(401)
  265. res.body.should.have.property('errors')
  266. res.body.errors.should.contain.something.that.deep.equals(Errors.invalidLoginCredentials)
  267. done()
  268. })
  269. })
  270. it('should throw an error if invalid password is provided', (done) => {
  271. chai.request(server)
  272. .post('/api/v1/user/username/login')
  273. .set('content-type', 'application/x-www-form-urlencoded')
  274. .send({
  275. password: 'invalid_password'
  276. })
  277. .end((err, res) => {
  278. res.should.have.status(401)
  279. res.body.should.have.property('errors')
  280. res.body.errors.should.contain.something.that.deep.equals(Errors.invalidLoginCredentials)
  281. done()
  282. })
  283. })
  284. it('should log in the user', (done) => {
  285. agent
  286. .post('/api/v1/user/username/login')
  287. .set('content-type', 'application/x-www-form-urlencoded')
  288. .send({
  289. password: 'password'
  290. })
  291. .end((err, res) => {
  292. res.should.have.status(200)
  293. res.should.be.json
  294. res.should.have.cookie('connect.sid')
  295. agent
  296. .get('/api/v1/user/username')
  297. .then((res) => {
  298. res.should.have.status(200)
  299. done()
  300. })
  301. .catch(done)
  302. })
  303. })
  304. })
  305. describe('/:username/logout POST user', () => {
  306. let agent = chai.request.agent(server)
  307. it('should log out the user', (done) => {
  308. agent
  309. .post('/api/v1/user/login')
  310. .set('content-type', 'application/x-www-form-urlencoded')
  311. .send({
  312. username: 'username',
  313. password: 'password'
  314. })
  315. .end((err, res) => {
  316. agent
  317. .post('/api/v1/user/username/logout')
  318. .end((err, res) => {
  319. res.should.have.status(200)
  320. agent
  321. .get('/api/v1/user/username')
  322. .then((res) => {
  323. res.should.have.status(403)
  324. res.body.errors.should.contain.something.that.deep.equals(Errors.requestNotAuthorized)
  325. done()
  326. })
  327. .catch((res) => {
  328. res.should.have.status(403)
  329. JSON
  330. .parse(res.response.text)
  331. .errors.should.contain.something
  332. .that.deep.equals(Errors.requestNotAuthorized)
  333. done()
  334. })
  335. })
  336. })
  337. })
  338. })
  339. })