UserMembershipAuthorizationTests.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. const { expect } = require('chai')
  2. const async = require('async')
  3. const { ObjectId } = require('../../../app/src/infrastructure/mongojs')
  4. const User = require('./helpers/User')
  5. const Institution = require('./helpers/Institution')
  6. const Subscription = require('./helpers/Subscription')
  7. const Publisher = require('./helpers/Publisher')
  8. const MockV1Api = require('./helpers/MockV1Api')
  9. describe('UserMembershipAuthorization', function() {
  10. beforeEach(function(done) {
  11. this.user = new User()
  12. async.series([this.user.ensureUserExists.bind(this.user)], done)
  13. })
  14. describe('team', function() {
  15. beforeEach(function(done) {
  16. this.subscription = new Subscription({
  17. groupPlan: true,
  18. overleaf: { id: 123 }
  19. })
  20. async.series(
  21. [
  22. this.subscription.ensureExists.bind(this.subscription),
  23. cb => this.user.login(cb)
  24. ],
  25. done
  26. )
  27. })
  28. describe('metrics', function() {
  29. it('should allow managers only', function(done) {
  30. const url = `/metrics/teams/123`
  31. async.series(
  32. [
  33. expectAccess(this.user, url, 403),
  34. cb => this.subscription.setManagerIds([this.user._id], cb),
  35. expectAccess(this.user, url, 200)
  36. ],
  37. done
  38. )
  39. })
  40. })
  41. })
  42. describe('group', function() {
  43. beforeEach(function(done) {
  44. this.subscription = new Subscription({
  45. groupPlan: true
  46. })
  47. async.series(
  48. [
  49. this.subscription.ensureExists.bind(this.subscription),
  50. cb => this.user.login(cb)
  51. ],
  52. done
  53. )
  54. })
  55. describe('users management', function() {
  56. it('should allow managers only', function(done) {
  57. const url = `/manage/groups/${this.subscription._id}/members`
  58. async.series(
  59. [
  60. expectAccess(this.user, url, 403),
  61. cb => this.subscription.setManagerIds([this.user._id], cb),
  62. expectAccess(this.user, url, 200)
  63. ],
  64. done
  65. )
  66. })
  67. })
  68. describe('metrics', function() {
  69. it('should allow managers only', function(done) {
  70. const url = `/metrics/groups/${this.subscription._id}`
  71. async.series(
  72. [
  73. expectAccess(this.user, url, 403),
  74. cb => this.subscription.setManagerIds([this.user._id], cb),
  75. expectAccess(this.user, url, 200)
  76. ],
  77. done
  78. )
  79. })
  80. it('should handle groups not found', function(done) {
  81. const url = `/metrics/groups/${ObjectId()}`
  82. async.series([expectAccess(this.user, url, 404)], done)
  83. })
  84. })
  85. describe('managers management', function() {
  86. it('should allow managers only', function(done) {
  87. const url = `/manage/groups/${this.subscription._id}/managers`
  88. async.series(
  89. [
  90. expectAccess(this.user, url, 403),
  91. cb => this.subscription.setManagerIds([this.user._id], cb),
  92. expectAccess(this.user, url, 200)
  93. ],
  94. done
  95. )
  96. })
  97. })
  98. })
  99. describe('institution', function() {
  100. beforeEach(function(done) {
  101. this.institution = new Institution()
  102. async.series([this.institution.ensureExists.bind(this.institution)], done)
  103. })
  104. describe('metrics', function() {
  105. it('should allow users with staff access', function(done) {
  106. const url = `/metrics/institutions/${this.institution.v1Id}`
  107. async.series(
  108. [
  109. cb => this.user.ensureStaffAccess('institutionMetrics', cb),
  110. this.user.login.bind(this.user),
  111. expectAccess(this.user, url, 200)
  112. ],
  113. done
  114. )
  115. })
  116. it('should allow admins', function(done) {
  117. const url = `/metrics/institutions/${this.institution.v1Id}`
  118. async.series(
  119. [
  120. this.user.ensureAdmin.bind(this.user),
  121. this.user.login.bind(this.user),
  122. expectAccess(this.user, url, 200)
  123. ],
  124. done
  125. )
  126. })
  127. it('should allow managers', function(done) {
  128. const url = `/metrics/institutions/${this.institution.v1Id}`
  129. async.series(
  130. [
  131. this.user.login.bind(this.user),
  132. cb => this.institution.setManagerIds([this.user._id], cb),
  133. expectAccess(this.user, url, 200)
  134. ],
  135. done
  136. )
  137. })
  138. it('should not allow users without access', function(done) {
  139. const url = `/metrics/institutions/${this.institution.v1Id}`
  140. async.series(
  141. [this.user.login.bind(this.user), expectAccess(this.user, url, 403)],
  142. done
  143. )
  144. })
  145. })
  146. describe('users management', function() {
  147. it('should allow managers only', function(done) {
  148. const url = `/manage/institutions/${this.institution.v1Id}/managers`
  149. async.series(
  150. [
  151. this.user.login.bind(this.user),
  152. expectAccess(this.user, url, 403),
  153. cb => this.institution.setManagerIds([this.user._id], cb),
  154. expectAccess(this.user, url, 200)
  155. ],
  156. done
  157. )
  158. })
  159. })
  160. describe('hub', function() {
  161. it('should allow managers only', function(done) {
  162. const url = `/institutions/${this.institution.v1Id}/hub`
  163. async.series(
  164. [
  165. this.user.login.bind(this.user),
  166. expectAccess(this.user, url, 403),
  167. cb => this.institution.setManagerIds([this.user._id], cb),
  168. expectAccess(this.user, url, 200)
  169. ],
  170. done
  171. )
  172. })
  173. })
  174. describe('creation', function() {
  175. it('should allow staff only', function(done) {
  176. const url = `/entities/institution/create/foo`
  177. async.series(
  178. [
  179. this.user.login.bind(this.user),
  180. expectAccess(this.user, url, 403),
  181. cb => this.user.ensureStaffAccess('institutionManagement', cb),
  182. this.user.login.bind(this.user),
  183. expectAccess(this.user, url, 200)
  184. ],
  185. done
  186. )
  187. })
  188. })
  189. })
  190. describe('publisher', function() {
  191. beforeEach(function(done) {
  192. this.publisher = new Publisher({})
  193. async.series(
  194. [
  195. this.publisher.ensureExists.bind(this.publisher),
  196. cb => this.user.login(cb)
  197. ],
  198. done
  199. )
  200. })
  201. describe('conversion metrics', function() {
  202. it('should allow managers only', function(done) {
  203. const url = `/metrics/conversions/${this.publisher.slug}`
  204. async.series(
  205. [
  206. expectAccess(this.user, url, 403),
  207. cb => this.publisher.setManagerIds([this.user._id], cb),
  208. expectAccess(this.user, url, 200)
  209. ],
  210. done
  211. )
  212. })
  213. })
  214. describe('managers management', function() {
  215. it('should allow managers only', function(done) {
  216. const url = `/manage/publishers/${this.publisher.slug}/managers`
  217. async.series(
  218. [
  219. expectAccess(this.user, url, 403),
  220. cb => this.publisher.setManagerIds([this.user._id], cb),
  221. expectAccess(this.user, url, 200)
  222. ],
  223. done
  224. )
  225. })
  226. })
  227. describe('creation', function() {
  228. it('should redirect staff only', function(done) {
  229. const url = `/publishers/foo/hub`
  230. async.series(
  231. [
  232. this.user.login.bind(this.user),
  233. expectAccess(this.user, url, 404),
  234. cb => this.user.ensureStaffAccess('publisherManagement', cb),
  235. this.user.login.bind(this.user),
  236. expectAccess(this.user, url, 302, /\/create/)
  237. ],
  238. done
  239. )
  240. })
  241. it('should allow staff only', function(done) {
  242. const url = `/entities/publisher/create/foo`
  243. async.series(
  244. [
  245. expectAccess(this.user, url, 403),
  246. cb => this.user.ensureStaffAccess('publisherManagement', cb),
  247. this.user.login.bind(this.user),
  248. expectAccess(this.user, url, 200)
  249. ],
  250. done
  251. )
  252. })
  253. })
  254. })
  255. describe('template', function() {
  256. beforeEach(function(done) {
  257. this.publisher = new Publisher({})
  258. async.series(
  259. [
  260. this.publisher.ensureExists.bind(this.publisher),
  261. cb => this.user.login(cb)
  262. ],
  263. done
  264. )
  265. })
  266. it('allow publisher managers only', function(done) {
  267. MockV1Api.setTemplates({
  268. 123: {
  269. id: 123,
  270. title: '123 title',
  271. brand: { slug: this.publisher.slug }
  272. }
  273. })
  274. const url = '/metrics/templates/123'
  275. async.series(
  276. [
  277. expectAccess(this.user, url, 403),
  278. cb => this.publisher.setManagerIds([this.user._id], cb),
  279. expectAccess(this.user, url, 200)
  280. ],
  281. done
  282. )
  283. })
  284. it('handle templates without publisher', function(done) {
  285. MockV1Api.setTemplates({
  286. 456: {
  287. id: 456,
  288. title: '456 title',
  289. brand: { slug: null }
  290. }
  291. })
  292. const url = '/metrics/templates/456'
  293. async.series(
  294. [
  295. expectAccess(this.user, url, 403),
  296. this.user.ensureAdmin.bind(this.user),
  297. this.user.login.bind(this.user),
  298. expectAccess(this.user, url, 200)
  299. ],
  300. done
  301. )
  302. })
  303. it('handle templates not found', function(done) {
  304. const url = '/metrics/templates/789'
  305. async.series(
  306. [
  307. this.user.ensureAdmin.bind(this.user),
  308. this.user.login.bind(this.user),
  309. expectAccess(this.user, url, 404)
  310. ],
  311. done
  312. )
  313. })
  314. })
  315. describe('graph', function() {
  316. describe('admin', function() {
  317. it('allow admins only', function(done) {
  318. const url = '/graphs/foo?resource_type=admin'
  319. async.series(
  320. [
  321. this.user.login.bind(this.user),
  322. expectAccess(this.user, url, 403),
  323. this.user.ensureAdmin.bind(this.user),
  324. this.user.login.bind(this.user),
  325. expectAccess(this.user, url, 200)
  326. ],
  327. done
  328. )
  329. })
  330. it('handle missing resource type', function(done) {
  331. const url = '/graphs/foo'
  332. expectAccess(this.user, url, 404)(done)
  333. })
  334. it('handle incorrect resource type', function(done) {
  335. const url = '/graphs/foo?resource_type=evil'
  336. expectAccess(this.user, url, 404)(done)
  337. })
  338. })
  339. describe('template', function() {
  340. beforeEach(function(done) {
  341. this.publisher = new Publisher({})
  342. async.series(
  343. [
  344. this.publisher.ensureExists.bind(this.publisher),
  345. cb => this.user.login(cb)
  346. ],
  347. done
  348. )
  349. })
  350. it('get template graphs', function(done) {
  351. MockV1Api.setTemplates({
  352. 123: {
  353. id: 123,
  354. title: '123 title',
  355. brand: { slug: this.publisher.slug }
  356. }
  357. })
  358. const url = '/graphs/foo?resource_type=template&resource_id=123'
  359. async.series(
  360. [
  361. this.user.ensureAdmin.bind(this.user),
  362. this.user.login.bind(this.user),
  363. expectAccess(this.user, url, 200)
  364. ],
  365. done
  366. )
  367. })
  368. })
  369. })
  370. describe('admin metrics', function() {
  371. it('should not allow anonymous users', function(done) {
  372. expectAccess(this.user, '/metrics/admin', 302, /\/login/)(done)
  373. })
  374. it('should not allow all users', function(done) {
  375. async.series(
  376. [
  377. this.user.login.bind(this.user),
  378. expectAccess(this.user, '/metrics/admin', 403)
  379. ],
  380. done
  381. )
  382. })
  383. it('should allow admin users', function(done) {
  384. async.series(
  385. [
  386. this.user.ensureAdmin.bind(this.user),
  387. this.user.login.bind(this.user),
  388. expectAccess(this.user, '/metrics/admin', 200)
  389. ],
  390. done
  391. )
  392. })
  393. it('should allow users with staff access', function(done) {
  394. async.series(
  395. [
  396. cb => this.user.ensureStaffAccess('adminMetrics', cb),
  397. this.user.login.bind(this.user),
  398. expectAccess(this.user, '/metrics/admin', 200)
  399. ],
  400. done
  401. )
  402. })
  403. })
  404. })
  405. function expectAccess(user, url, status, pattern) {
  406. return callback => {
  407. user.request.get({ url }, (error, response, body) => {
  408. if (error) {
  409. return callback(error)
  410. }
  411. expect(response.statusCode).to.equal(status)
  412. if (pattern) {
  413. expect(body).to.match(pattern)
  414. }
  415. callback()
  416. })
  417. }
  418. }