expressa 2.0.15 → 2.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/.circleci/config.yml +21 -21
  2. package/.eslintrc.json +29 -29
  3. package/LICENSE +21 -21
  4. package/README.md +137 -137
  5. package/auth/index.js +76 -76
  6. package/auth/jwt.js +31 -31
  7. package/controllers/collections.js +258 -258
  8. package/controllers/install.js +105 -105
  9. package/controllers/status.js +43 -43
  10. package/controllers/users.js +52 -52
  11. package/cypress/fixtures/example.json +4 -4
  12. package/cypress/integration/0_install_spec.js +8 -8
  13. package/cypress/integration/custom_collections.js +28 -28
  14. package/cypress/integration/home.js +9 -9
  15. package/cypress/integration/settings.js +34 -34
  16. package/cypress/integration/users.js +61 -61
  17. package/cypress/plugins/index.js +17 -17
  18. package/cypress/screenshots/users.js/User Management -- Can log in as non-admin, but cannot create users (failed).png +0 -0
  19. package/cypress/support/commands.js +54 -54
  20. package/cypress/support/index.js +20 -20
  21. package/cypress/support/util.js +10 -10
  22. package/cypress.json +4 -4
  23. package/db/cached.js +40 -40
  24. package/db/file.js +112 -112
  25. package/db/memory.js +79 -79
  26. package/db/mongo.js +86 -86
  27. package/db/postgres.js +93 -93
  28. package/doc/authentication.md +38 -38
  29. package/doc/automatic-fields.md +12 -12
  30. package/doc/blogexample.md +16 -16
  31. package/doc/custom-endpoints.md +20 -20
  32. package/doc/database.md +23 -23
  33. package/doc/development.md +33 -33
  34. package/doc/listeners.md +103 -103
  35. package/doc/modules.md +8 -8
  36. package/doc/permissions.md +14 -14
  37. package/doc/relationships.md +65 -65
  38. package/doc/testing.md +47 -47
  39. package/doc/uploading-files.md +53 -53
  40. package/index.js +297 -297
  41. package/listeners.js +65 -65
  42. package/listeners_collection_permissions.js +29 -29
  43. package/listeners_users.js +96 -96
  44. package/listeners_validation.js +43 -43
  45. package/middleware/logging.js +30 -30
  46. package/middleware/permissions.js +41 -41
  47. package/modules/access_keys/access_keys.js +32 -32
  48. package/modules/admin/.babelrc +20 -12
  49. package/modules/admin/.editorconfig +14 -14
  50. package/modules/admin/.eslintignore +5 -5
  51. package/modules/admin/.eslintrc.js +197 -197
  52. package/modules/admin/.postcssrc.js +10 -10
  53. package/modules/admin/.travis.yml +5 -5
  54. package/modules/admin/LICENSE +21 -21
  55. package/modules/admin/README.md +88 -88
  56. package/modules/admin/build/build.js +45 -45
  57. package/modules/admin/build/check-versions.js +64 -64
  58. package/modules/admin/build/utils.js +108 -108
  59. package/modules/admin/build/vue-loader.conf.js +5 -5
  60. package/modules/admin/build/webpack.base.conf.js +112 -108
  61. package/modules/admin/build/webpack.dev.conf.js +95 -95
  62. package/modules/admin/build/webpack.prod.conf.js +112 -171
  63. package/modules/admin/config/dev.env.js +8 -8
  64. package/modules/admin/config/index.js +86 -86
  65. package/modules/admin/config/prod.env.js +5 -5
  66. package/modules/admin/dist/164c6167c1f3c497c07c.woff +1 -0
  67. package/modules/admin/dist/42ac07abc8473600c41f.ttf +1 -0
  68. package/modules/admin/dist/86dccb18a7eb4be8ef1a.woff +1 -0
  69. package/modules/admin/dist/c45297c558e0318fc9c5.ttf +1 -0
  70. package/modules/admin/dist/c717c9930715e24fa12c.woff +1 -0
  71. package/modules/admin/dist/ca6f07ef23f24cc2738a.ttf +1 -0
  72. package/modules/admin/dist/css/269.f7d5c7d5.css +37 -0
  73. package/modules/admin/dist/css/269.f7d5c7d5.css.gz +0 -0
  74. package/modules/admin/dist/css/451.c6646d20.css +1 -0
  75. package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
  76. package/modules/admin/dist/css/572.74d8e965.css +34 -0
  77. package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
  78. package/modules/admin/dist/css/651.e946bda7.css +6 -0
  79. package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
  80. package/modules/admin/dist/css/699.d1f90954.css +8 -0
  81. package/modules/admin/dist/css/699.d1f90954.css.gz +0 -0
  82. package/modules/admin/dist/css/750.4086915d.css +2 -0
  83. package/modules/admin/dist/css/750.4086915d.css.gz +0 -0
  84. package/modules/admin/dist/css/864.506917a4.css +7 -0
  85. package/modules/admin/dist/css/864.506917a4.css.gz +0 -0
  86. package/modules/admin/dist/css/899.506917a4.css +7 -0
  87. package/modules/admin/dist/css/899.506917a4.css.gz +0 -0
  88. package/modules/admin/dist/css/950.1fd9d57c.css +7 -0
  89. package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
  90. package/modules/admin/dist/css/app.11cc6245.css +39 -0
  91. package/modules/admin/dist/css/app.11cc6245.css.gz +0 -0
  92. package/modules/admin/dist/css/app.2e1b0d79.css +591 -0
  93. package/modules/admin/dist/css/app.2e1b0d79.css.gz +0 -0
  94. package/modules/admin/dist/css/app.4d43d0fd.css +592 -0
  95. package/modules/admin/dist/css/app.4d43d0fd.css.gz +0 -0
  96. package/modules/admin/dist/css/app.abace109.css +1 -0
  97. package/modules/admin/dist/css/app.abace109.css.gz +0 -0
  98. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css +1 -0
  99. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css.gz +0 -0
  100. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css +1 -0
  101. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css.gz +0 -0
  102. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css +1 -0
  103. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css.gz +0 -0
  104. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css +1 -0
  105. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css.gz +0 -0
  106. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css +1 -0
  107. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css.gz +0 -0
  108. package/modules/admin/dist/css/chunk-libs.de0d8484.css +551 -0
  109. package/modules/admin/dist/css/chunk-libs.de0d8484.css.gz +0 -0
  110. package/modules/admin/dist/index.html +1 -1
  111. package/modules/admin/dist/static/fonts/element-icons.313f7da.woff +0 -0
  112. package/modules/admin/dist/static/fonts/element-icons.4520188.ttf +0 -0
  113. package/modules/admin/dist/static/js/269.7245ceaf.js +1 -0
  114. package/modules/admin/dist/static/js/269.7245ceaf.js.gz +0 -0
  115. package/modules/admin/dist/static/js/451.645974a8.js +1 -0
  116. package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
  117. package/modules/admin/dist/static/js/460.962d5bc0.js +1 -0
  118. package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
  119. package/modules/admin/dist/static/js/556.1e08866a.js +1 -0
  120. package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
  121. package/modules/admin/dist/static/js/572.13392e1d.js +1 -0
  122. package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
  123. package/modules/admin/dist/static/js/603.7b34a650.js +1 -0
  124. package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
  125. package/modules/admin/dist/static/js/637.26413baa.js +1 -0
  126. package/modules/admin/dist/static/js/637.26413baa.js.gz +0 -0
  127. package/modules/admin/dist/static/js/651.564b24b6.js +1 -0
  128. package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
  129. package/modules/admin/dist/static/js/653.02ec1098.js +1 -0
  130. package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
  131. package/modules/admin/dist/static/js/699.c7564884.js +1 -0
  132. package/modules/admin/dist/static/js/699.c7564884.js.gz +0 -0
  133. package/modules/admin/dist/static/js/750.50c950da.js +1 -0
  134. package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
  135. package/modules/admin/dist/static/js/864.4f43847d.js +1 -0
  136. package/modules/admin/dist/static/js/864.4f43847d.js.gz +0 -0
  137. package/modules/admin/dist/static/js/950.d4ff0a18.js +1 -0
  138. package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
  139. package/modules/admin/dist/static/js/app.981e71b3.js +2 -0
  140. package/modules/admin/dist/static/js/{chunk-libs.06c38828.js.LICENSE.txt → app.981e71b3.js.LICENSE.txt} +15 -18
  141. package/modules/admin/dist/static/js/app.981e71b3.js.LICENSE.txt.gz +0 -0
  142. package/modules/admin/dist/static/js/app.981e71b3.js.gz +0 -0
  143. package/modules/admin/index.html +16 -16
  144. package/modules/admin/package.json +101 -98
  145. package/modules/admin/src/App.vue +11 -11
  146. package/modules/admin/src/api/login.js +26 -26
  147. package/modules/admin/src/api/table.js +9 -9
  148. package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
  149. package/modules/admin/src/components/Hamburger/index.vue +62 -62
  150. package/modules/admin/src/components/JSONEditor.vue +180 -180
  151. package/modules/admin/src/components/SvgIcon/index.vue +43 -43
  152. package/modules/admin/src/icons/index.js +9 -9
  153. package/modules/admin/src/icons/svgo.yml +22 -22
  154. package/modules/admin/src/main.js +1 -0
  155. package/modules/admin/src/permission.js +49 -49
  156. package/modules/admin/src/router/index.js +200 -200
  157. package/modules/admin/src/store/getters.js +11 -11
  158. package/modules/admin/src/store/index.js +17 -17
  159. package/modules/admin/src/store/modules/app.js +43 -43
  160. package/modules/admin/src/store/modules/user.js +104 -104
  161. package/modules/admin/src/styles/element-ui.scss +29 -29
  162. package/modules/admin/src/styles/index.scss +78 -78
  163. package/modules/admin/src/styles/mixin.scss +27 -27
  164. package/modules/admin/src/styles/sidebar.scss +133 -133
  165. package/modules/admin/src/styles/transition.scss +46 -46
  166. package/modules/admin/src/styles/variables.scss +4 -4
  167. package/modules/admin/src/utils/auth.js +15 -15
  168. package/modules/admin/src/utils/index.js +74 -74
  169. package/modules/admin/src/utils/request.js +48 -48
  170. package/modules/admin/src/utils/validate.js +31 -31
  171. package/modules/admin/src/views/404.vue +235 -235
  172. package/modules/admin/src/views/Dev.vue +33 -33
  173. package/modules/admin/src/views/EditDocument.vue +116 -116
  174. package/modules/admin/src/views/Endpoints.vue +279 -279
  175. package/modules/admin/src/views/Home.vue +84 -84
  176. package/modules/admin/src/views/Install.vue +79 -79
  177. package/modules/admin/src/views/ListDocuments.vue +72 -72
  178. package/modules/admin/src/views/ListDocuments2.vue +462 -462
  179. package/modules/admin/src/views/ManageListeners.vue +67 -67
  180. package/modules/admin/src/views/ManageMiddleware.vue +43 -43
  181. package/modules/admin/src/views/ManagePermissions.vue +75 -75
  182. package/modules/admin/src/views/ViewRequest.vue +77 -77
  183. package/modules/admin/src/views/form/index.vue +91 -91
  184. package/modules/admin/src/views/layout/Layout.vue +69 -69
  185. package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
  186. package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
  187. package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
  188. package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
  189. package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
  190. package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
  191. package/modules/admin/src/views/layout/components/index.js +3 -3
  192. package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
  193. package/modules/admin/src/views/login/index.vue +195 -195
  194. package/modules/admin/src/views/tree/index.vue +77 -77
  195. package/modules/collections/collections.js +39 -39
  196. package/modules/core/core.js +197 -197
  197. package/modules/logging/logging.js +88 -88
  198. package/modules/permissions/permissions.js +106 -106
  199. package/package.json +59 -59
  200. package/scripts/expressa +12 -12
  201. package/scripts/run_cypress_tests.sh +5 -5
  202. package/scripts/run_db_tests.sh +8 -8
  203. package/test/0-install.js +96 -96
  204. package/test/collections.js +431 -423
  205. package/test/collections.querying.js +288 -269
  206. package/test/db.js +258 -250
  207. package/test/db.strings.js +73 -73
  208. package/test/db.updating.js +144 -144
  209. package/test/logging.js +29 -29
  210. package/test/test.js +93 -94
  211. package/test/testserver.js +17 -17
  212. package/test/testutils.js +136 -136
  213. package/test/users.js +425 -425
  214. package/util.js +522 -521
  215. package/modules/admin/dist/index.html.gz +0 -0
  216. package/modules/admin/dist/static/css/app.9dd57eea.css +0 -1
  217. package/modules/admin/dist/static/css/app.9dd57eea.css.gz +0 -0
  218. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css +0 -1
  219. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css.gz +0 -0
  220. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css +0 -1
  221. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css.gz +0 -0
  222. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css +0 -1
  223. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css.gz +0 -0
  224. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css +0 -1
  225. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css.gz +0 -0
  226. package/modules/admin/dist/static/css/chunk-7291.13514e45.css +0 -0
  227. package/modules/admin/dist/static/css/chunk-7291.13514e45.css.gz +0 -0
  228. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css +0 -1
  229. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css.gz +0 -0
  230. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css +0 -1
  231. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css.gz +0 -0
  232. package/modules/admin/dist/static/css/chunk-b423.5f239333.css +0 -0
  233. package/modules/admin/dist/static/css/chunk-b423.5f239333.css.gz +0 -0
  234. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css +0 -1
  235. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css.gz +0 -0
  236. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css +0 -1
  237. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css.gz +0 -0
  238. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css +0 -1
  239. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css.gz +0 -0
  240. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css +0 -1
  241. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css.gz +0 -0
  242. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css +0 -14
  243. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css.gz +0 -0
  244. package/modules/admin/dist/static/fonts/element-icons.6f0a763.ttf +0 -0
  245. package/modules/admin/dist/static/js/app.e9461593.js +0 -1
  246. package/modules/admin/dist/static/js/app.e9461593.js.gz +0 -0
  247. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js +0 -2
  248. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt +0 -13
  249. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt.gz +0 -0
  250. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.gz +0 -0
  251. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js +0 -1
  252. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js.gz +0 -0
  253. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js +0 -1
  254. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js.gz +0 -0
  255. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js +0 -1
  256. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js.gz +0 -0
  257. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js +0 -1
  258. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js.gz +0 -0
  259. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js +0 -1
  260. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js.gz +0 -0
  261. package/modules/admin/dist/static/js/chunk-7291.590524e9.js +0 -1
  262. package/modules/admin/dist/static/js/chunk-7291.590524e9.js.gz +0 -0
  263. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js +0 -1
  264. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js.gz +0 -0
  265. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js +0 -1
  266. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js.gz +0 -0
  267. package/modules/admin/dist/static/js/chunk-b423.387c504c.js +0 -1
  268. package/modules/admin/dist/static/js/chunk-b423.387c504c.js.gz +0 -0
  269. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js +0 -1
  270. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js.gz +0 -0
  271. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js +0 -1
  272. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js.gz +0 -0
  273. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js +0 -1
  274. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js.gz +0 -0
  275. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js +0 -1
  276. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js.gz +0 -0
  277. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js +0 -1
  278. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js.gz +0 -0
  279. package/modules/admin/dist/static/js/chunk-libs.06c38828.js +0 -2
  280. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.LICENSE.txt.gz +0 -0
  281. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.gz +0 -0
  282. /package/modules/admin/dist/static/img/{404.a57b6f3.png → 404.4cf6930.png} +0 -0
@@ -1,106 +1,106 @@
1
- const { collectionPermissions, collectionOwnerPermissions } = require('../collections/collections')
2
-
3
- exports.settingSchema = {
4
- enforce_permissions: {
5
- type: 'boolean',
6
- description: 'Whether permissions should be checked. Only turn off if needed for testing.',
7
- default: true,
8
- format: 'checkbox',
9
- }
10
- }
11
-
12
- exports.collections = [{
13
- _id: 'role',
14
- schema: {
15
- type: 'object',
16
- additionalProperties: false,
17
- properties: {
18
- _id: {
19
- type: 'string'
20
- },
21
- permissions: {
22
- type: 'object',
23
- additionalProperties: true,
24
- properties: {},
25
- description: 'list of permissions this role has'
26
- }
27
- },
28
- required: [
29
- '_id',
30
- 'permissions'
31
- ]
32
- },
33
- cacheInMemory: true,
34
- documentsHaveOwners: false
35
- }]
36
-
37
- exports.install = async function (app) {
38
- app.db.role.create({
39
- _id: 'Admin',
40
- permissions: {}
41
- })
42
-
43
- app.db.role.create({
44
- _id: 'Authenticated',
45
- permissions: {
46
- 'users: view own': 1,
47
- 'users: edit own': 1,
48
- 'users: delete own': 1,
49
- }
50
- })
51
-
52
- app.db.role.create({
53
- _id: 'Anonymous',
54
- permissions: {
55
- 'users: create': 1
56
- }
57
- })
58
- }
59
-
60
- exports.permissions = ['users: modify roles', 'login to admin']
61
-
62
- exports.init = async function (api) {
63
- api.addCollectionListener(['changed'], 'collection', async function addCollectionPerms (req, collection, data) {
64
- if (api.db.role) {
65
- try {
66
- const admin = await api.db.role.get('Admin')
67
- collectionPermissions(data._id).forEach(function (permission) {
68
- if (admin.permissions[permission] == null) {
69
- admin.permissions[permission] = 1
70
- }
71
- })
72
- collectionOwnerPermissions(data._id).forEach(function (permission) {
73
- if (data.documentsHaveOwners) {
74
- if (admin.permissions[permission] == null) {
75
- admin.permissions[permission] = 1
76
- }
77
- }
78
- else {
79
- delete admin.permissions[permission]
80
- }
81
- })
82
- await api.db.role.update('Admin', admin)
83
- } catch (e) {
84
- // This error is expected if install is not complete
85
- if (api.installed || e.message !== 'document not found') {
86
- console.error('Error updating admin role with permissions')
87
- console.error(e)
88
- console.error(e.message)
89
- }
90
- }
91
- }
92
- })
93
-
94
- api.addCollectionListener('delete', 'collection', async function removeCollectionPerms (req, collection, data) {
95
- if (api.db.role) {
96
- const coll = data._id
97
- const admin = await api.db.role.get('Admin')
98
- const permissions = collectionPermissions(coll).concat(collectionOwnerPermissions(coll))
99
- permissions.forEach((permission) => {
100
- delete admin.permissions[permission]
101
- })
102
- await api.db.role.update('Admin', admin)
103
- }
104
- })
105
-
106
- }
1
+ const { collectionPermissions, collectionOwnerPermissions } = require('../collections/collections')
2
+
3
+ exports.settingSchema = {
4
+ enforce_permissions: {
5
+ type: 'boolean',
6
+ description: 'Whether permissions should be checked. Only turn off if needed for testing.',
7
+ default: true,
8
+ format: 'checkbox',
9
+ }
10
+ }
11
+
12
+ exports.collections = [{
13
+ _id: 'role',
14
+ schema: {
15
+ type: 'object',
16
+ additionalProperties: false,
17
+ properties: {
18
+ _id: {
19
+ type: 'string'
20
+ },
21
+ permissions: {
22
+ type: 'object',
23
+ additionalProperties: true,
24
+ properties: {},
25
+ description: 'list of permissions this role has'
26
+ }
27
+ },
28
+ required: [
29
+ '_id',
30
+ 'permissions'
31
+ ]
32
+ },
33
+ cacheInMemory: true,
34
+ documentsHaveOwners: false
35
+ }]
36
+
37
+ exports.install = async function (app) {
38
+ app.db.role.create({
39
+ _id: 'Admin',
40
+ permissions: {}
41
+ })
42
+
43
+ app.db.role.create({
44
+ _id: 'Authenticated',
45
+ permissions: {
46
+ 'users: view own': 1,
47
+ 'users: edit own': 1,
48
+ 'users: delete own': 1,
49
+ }
50
+ })
51
+
52
+ app.db.role.create({
53
+ _id: 'Anonymous',
54
+ permissions: {
55
+ 'users: create': 1
56
+ }
57
+ })
58
+ }
59
+
60
+ exports.permissions = ['users: modify roles', 'login to admin']
61
+
62
+ exports.init = async function (api) {
63
+ api.addCollectionListener(['changed'], 'collection', async function addCollectionPerms (req, collection, data) {
64
+ if (api.db.role) {
65
+ try {
66
+ const admin = await api.db.role.get('Admin')
67
+ collectionPermissions(data._id).forEach(function (permission) {
68
+ if (admin.permissions[permission] == null) {
69
+ admin.permissions[permission] = 1
70
+ }
71
+ })
72
+ collectionOwnerPermissions(data._id).forEach(function (permission) {
73
+ if (data.documentsHaveOwners) {
74
+ if (admin.permissions[permission] == null) {
75
+ admin.permissions[permission] = 1
76
+ }
77
+ }
78
+ else {
79
+ delete admin.permissions[permission]
80
+ }
81
+ })
82
+ await api.db.role.update('Admin', admin)
83
+ } catch (e) {
84
+ // This error is expected if install is not complete
85
+ if (api.installed || e.message !== 'document not found') {
86
+ console.error('Error updating admin role with permissions')
87
+ console.error(e)
88
+ console.error(e.message)
89
+ }
90
+ }
91
+ }
92
+ })
93
+
94
+ api.addCollectionListener('delete', 'collection', async function removeCollectionPerms (req, collection, data) {
95
+ if (api.db.role) {
96
+ const coll = data._id
97
+ const admin = await api.db.role.get('Admin')
98
+ const permissions = collectionPermissions(coll).concat(collectionOwnerPermissions(coll))
99
+ permissions.forEach((permission) => {
100
+ delete admin.permissions[permission]
101
+ })
102
+ await api.db.role.update('Admin', admin)
103
+ }
104
+ })
105
+
106
+ }
package/package.json CHANGED
@@ -1,59 +1,59 @@
1
- {
2
- "name": "expressa",
3
- "version": "2.0.15",
4
- "description": "API framework using JSON schemas",
5
- "main": "index.js",
6
- "repository": "https://github.com/thomas4019/expressa",
7
- "bin": {
8
- "expressa": "./scripts/expressa"
9
- },
10
- "dependencies": {
11
- "ajv": "^8.1.0",
12
- "bcryptjs": "2.4.3",
13
- "body-parser": "^1.19.0",
14
- "debug": "^2.6.1",
15
- "dot-object": "^2.1.4",
16
- "express": "^4.17.1",
17
- "jfs": "^0.3.0",
18
- "jsonwebtoken": "^9.0.0",
19
- "mongo-query": "^0.5.7",
20
- "mongo-query-to-postgres-jsonb": "^0.2.17",
21
- "mongo-querystring": "4.1.1",
22
- "mongodb": "^3.5.7",
23
- "on-finished": "^2.3.0",
24
- "pg": "^8.4.2",
25
- "randomstring": "1.1.4",
26
- "sift": "^5.1.0",
27
- "uuid": "^8.3.0"
28
- },
29
- "devDependencies": {
30
- "chai": "^4.2.0",
31
- "cross-env": "^7.0.2",
32
- "cypress": "^9.2.0",
33
- "eslint": "^7.1.0",
34
- "mocha": "^9.1.3",
35
- "mocha-junit-reporter": "^2.0.2",
36
- "nodemon": "^2.0.4",
37
- "rimraf": "^3.0.2",
38
- "supertest": "^3.4.2"
39
- },
40
- "engines": {
41
- "node": ">= 8.1.4"
42
- },
43
- "author": "Thomas Hansen <th4019@example.com> (http://thomashansen.me)",
44
- "scripts": {
45
- "test": "cross-env NODE_ENV=local_test_suite mocha --exit",
46
- "testlint": "cross-env NODE_ENV=local_test_suite mocha --exit && npm run lint",
47
- "testdebug": "cross-env NODE_ENV=local_test_suite DEBUG=expressa mocha -b --exit && npm run lint",
48
- "ci-test": "cross-env NODE_ENV=local_test_suite mocha test --reporter mocha-junit-reporter --exit",
49
- "clean": "rimraf node_modules",
50
- "lint": "eslint .",
51
- "fixlint": "eslint . --fix",
52
- "testserver": "rimraf testdata && node test/testserver.js",
53
- "testserver-watch": "rimraf testdata && nodemon test/testserver.js",
54
- "cypress": "cypress open",
55
- "testdbs": "./scripts/run_db_tests.sh",
56
- "testcypress": "./scripts/run_cypress_tests.sh"
57
- },
58
- "license": "MIT"
59
- }
1
+ {
2
+ "name": "expressa",
3
+ "version": "2.0.17",
4
+ "description": "API framework using JSON schemas",
5
+ "main": "index.js",
6
+ "repository": "https://github.com/thomas4019/expressa",
7
+ "bin": {
8
+ "expressa": "./scripts/expressa"
9
+ },
10
+ "dependencies": {
11
+ "ajv": "^8.1.0",
12
+ "bcryptjs": "2.4.3",
13
+ "body-parser": "^1.19.0",
14
+ "debug": "^2.6.1",
15
+ "dot-object": "^2.1.4",
16
+ "express": "^4.17.1",
17
+ "jfs": "^0.3.0",
18
+ "jsonwebtoken": "^9.0.0",
19
+ "mongo-query": "^0.5.7",
20
+ "mongo-query-to-postgres-jsonb": "^0.2.17",
21
+ "mongo-querystring": "4.1.1",
22
+ "mongodb": "^3.5.7",
23
+ "on-finished": "^2.3.0",
24
+ "pg": "^8.4.2",
25
+ "randomstring": "1.1.4",
26
+ "sift": "^5.1.0",
27
+ "uuid": "^8.3.0"
28
+ },
29
+ "devDependencies": {
30
+ "chai": "^4.2.0",
31
+ "cross-env": "^7.0.2",
32
+ "cypress": "^9.2.0",
33
+ "eslint": "^7.1.0",
34
+ "mocha": "^9.1.3",
35
+ "mocha-junit-reporter": "^2.0.2",
36
+ "nodemon": "^2.0.4",
37
+ "rimraf": "^3.0.2",
38
+ "supertest": "^3.4.2"
39
+ },
40
+ "engines": {
41
+ "node": ">= 8.1.4"
42
+ },
43
+ "author": "Thomas Hansen <th4019@example.com> (http://thomashansen.me)",
44
+ "scripts": {
45
+ "test": "cross-env NODE_ENV=local_test_suite mocha --exit",
46
+ "testlint": "cross-env NODE_ENV=local_test_suite mocha --exit && npm run lint",
47
+ "testdebug": "cross-env NODE_ENV=local_test_suite DEBUG=expressa mocha -b --exit && npm run lint",
48
+ "ci-test": "cross-env NODE_ENV=local_test_suite mocha test --reporter mocha-junit-reporter --exit",
49
+ "clean": "rimraf node_modules",
50
+ "lint": "eslint .",
51
+ "fixlint": "eslint . --fix",
52
+ "testserver": "rimraf testdata && node test/testserver.js",
53
+ "testserver-watch": "rimraf testdata && nodemon test/testserver.js",
54
+ "cypress": "cypress open",
55
+ "testdbs": "./scripts/run_db_tests.sh",
56
+ "testcypress": "./scripts/run_cypress_tests.sh"
57
+ },
58
+ "license": "MIT"
59
+ }
package/scripts/expressa CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
-
3
- 'use strict';
4
-
5
- var express = require('express');
6
- var app = express();
7
-
8
- var expressa = require('../');
9
- app.use('/api', expressa.api()); // optionally pass in settings
10
- app.use('/admin', expressa.admin({ apiurl: '/api/' }));
11
-
12
- app.listen(3000, function () {
13
- console.log('Example app listening on port 3000!');
2
+
3
+ 'use strict';
4
+
5
+ var express = require('express');
6
+ var app = express();
7
+
8
+ var expressa = require('../');
9
+ app.use('/api', expressa.api()); // optionally pass in settings
10
+ app.use('/admin', expressa.admin({ apiurl: '/api/' }));
11
+
12
+ app.listen(3000, function () {
13
+ console.log('Example app listening on port 3000!');
14
14
  });
@@ -1,6 +1,6 @@
1
- rm -rf testdata
2
- node test/testserver.js &
3
- pid=$!
4
- sleep 1
5
- ./node_modules/.bin/cypress run
1
+ rm -rf testdata
2
+ node test/testserver.js &
3
+ pid=$!
4
+ sleep 1
5
+ ./node_modules/.bin/cypress run
6
6
  kill "$pid"
@@ -1,8 +1,8 @@
1
- docker run -d -p 5432:5432 --rm --name postgres -e POSTGRES_PASSWORD=expressa postgres
2
- docker run -d -p 27017:27017 --rm --name mongo mongo
3
- sleep 1
4
- docker exec -it postgres /bin/bash -c "createdb pgtest -U postgres"
5
- TEST_POSTGRES=true TEST_MONGO=true npm run test
6
-
7
- docker stop postgres
8
- docker stop mongo
1
+ docker run -d -p 5432:5432 --rm --name postgres -e POSTGRES_PASSWORD=expressa postgres
2
+ docker run -d -p 27017:27017 --rm --name mongo mongo
3
+ sleep 1
4
+ docker exec -it postgres /bin/bash -c "createdb pgtest -U postgres"
5
+ TEST_POSTGRES=true TEST_MONGO=true npm run test
6
+
7
+ docker stop postgres
8
+ docker stop mongo
package/test/0-install.js CHANGED
@@ -1,96 +1,96 @@
1
- const request = require('supertest')
2
- const chai = require('chai')
3
- const expect = chai.expect
4
- const testutils = require('./testutils')
5
- const { app, api } = testutils
6
-
7
- describe('install flow', function () {
8
- it('can get settings schema', async function() {
9
- const { body } = await request(app)
10
- .get('/install/settings/schema')
11
- .expect(200)
12
- expect(body.schema.properties.jwt_secret).to.eql({
13
- type: 'string',
14
- description: 'The secret key used to encode your json web tokens. It\'s important this is kept unique and secret.'
15
- })
16
- })
17
-
18
- it('call install', async function () {
19
- expect(api.db.collections).to.not.exist
20
-
21
- await request(app)
22
- .post('/install')
23
- .send({
24
- modules: ['collections', 'core', 'logging', 'permissions', 'access_keys'],
25
- settings: {
26
- jwt_secret: 'testing 123',
27
- jwt_expire_on_password_change: true,
28
- mongodb_uri: 'mongodb://localhost:27017/test',
29
- postgresql_uri: 'postgresql://postgres:expressa@localhost/pgtest',
30
- enforce_permissions: true,
31
- user_storage: 'mongo'
32
- }
33
- })
34
- .expect(200)
35
-
36
- expect(api.db.collection).to.exist
37
- expect(api.db.role).to.exist
38
- expect(api.db.users).to.exist
39
- expect(api.settings.jwt_secret.length).to.be.greaterThan(20)
40
-
41
- // Check storage of users set correctly and then restore to 'file'
42
- const userCollection = (await api.db.collection.find({ _id: 'users' }))[0]
43
- expect(userCollection.storage).to.eql('mongo')
44
- userCollection.storage = 'file'
45
- await api.db.collection.update(null, userCollection)
46
- api.setupCollectionDb(userCollection)
47
-
48
- const userCollection2 = (await api.db.collection.find({ _id: 'users' }))[0]
49
- expect(userCollection2.storage).to.eql('file')
50
- })
51
-
52
- it('can create admin account', async function() {
53
- const res = await request(app)
54
- .post('/users/register')
55
- .send({
56
- email: 'a@example.com',
57
- roles: ['Admin'],
58
- password: '123'
59
- })
60
- .expect(200)
61
- const id = res.body.id
62
- const u = await api.db.users.get(id)
63
- expect(u.roles || []).to.include('Admin')
64
- })
65
-
66
- it('can login admin account', async function() {
67
- const res = await request(app)
68
- .post('/users/login')
69
- .send({
70
- email: 'a@example.com',
71
- password: '123'
72
- })
73
- .expect(200)
74
- testutils.setAdminToken(res.body.token)
75
- })
76
-
77
- it('2nd account cannot be admin account', async function() {
78
- await request(app)
79
- .post('/users/register')
80
- .send({
81
- email: 'try2@example.com',
82
- roles: ['Admin'],
83
- password: 'admin2'
84
- })
85
- .expect(400)
86
- })
87
-
88
- it('admin should have many permissions set', async function () {
89
- const admin = await api.db.role.get('Admin')
90
- expect(admin.permissions).deep.include({
91
- 'view errors': 1,
92
- 'collection: create': 1,
93
- 'users: edit own': 1
94
- })
95
- })
96
- })
1
+ const request = require('supertest')
2
+ const chai = require('chai')
3
+ const expect = chai.expect
4
+ const testutils = require('./testutils')
5
+ const { app, api } = testutils
6
+
7
+ describe('install flow', function () {
8
+ it('can get settings schema', async function() {
9
+ const { body } = await request(app)
10
+ .get('/install/settings/schema')
11
+ .expect(200)
12
+ expect(body.schema.properties.jwt_secret).to.eql({
13
+ type: 'string',
14
+ description: 'The secret key used to encode your json web tokens. It\'s important this is kept unique and secret.'
15
+ })
16
+ })
17
+
18
+ it('call install', async function () {
19
+ expect(api.db.collections).to.not.exist
20
+
21
+ await request(app)
22
+ .post('/install')
23
+ .send({
24
+ modules: ['collections', 'core', 'logging', 'permissions', 'access_keys'],
25
+ settings: {
26
+ jwt_secret: 'testing 123',
27
+ jwt_expire_on_password_change: true,
28
+ mongodb_uri: 'mongodb://localhost:27017/test',
29
+ postgresql_uri: 'postgresql://postgres:expressa@localhost/pgtest',
30
+ enforce_permissions: true,
31
+ user_storage: 'mongo'
32
+ }
33
+ })
34
+ .expect(200)
35
+
36
+ expect(api.db.collection).to.exist
37
+ expect(api.db.role).to.exist
38
+ expect(api.db.users).to.exist
39
+ expect(api.settings.jwt_secret.length).to.be.greaterThan(20)
40
+
41
+ // Check storage of users set correctly and then restore to 'file'
42
+ const userCollection = (await api.db.collection.find({ _id: 'users' }))[0]
43
+ expect(userCollection.storage).to.eql('mongo')
44
+ userCollection.storage = 'file'
45
+ await api.db.collection.update(null, userCollection)
46
+ api.setupCollectionDb(userCollection)
47
+
48
+ const userCollection2 = (await api.db.collection.find({ _id: 'users' }))[0]
49
+ expect(userCollection2.storage).to.eql('file')
50
+ })
51
+
52
+ it('can create admin account', async function() {
53
+ const res = await request(app)
54
+ .post('/users/register')
55
+ .send({
56
+ email: 'a@example.com',
57
+ roles: ['Admin'],
58
+ password: '123'
59
+ })
60
+ .expect(200)
61
+ const id = res.body.id
62
+ const u = await api.db.users.get(id)
63
+ expect(u.roles || []).to.include('Admin')
64
+ })
65
+
66
+ it('can login admin account', async function() {
67
+ const res = await request(app)
68
+ .post('/users/login')
69
+ .send({
70
+ email: 'a@example.com',
71
+ password: '123'
72
+ })
73
+ .expect(200)
74
+ testutils.setAdminToken(res.body.token)
75
+ })
76
+
77
+ it('2nd account cannot be admin account', async function() {
78
+ await request(app)
79
+ .post('/users/register')
80
+ .send({
81
+ email: 'try2@example.com',
82
+ roles: ['Admin'],
83
+ password: 'admin2'
84
+ })
85
+ .expect(400)
86
+ })
87
+
88
+ it('admin should have many permissions set', async function () {
89
+ const admin = await api.db.role.get('Admin')
90
+ expect(admin.permissions).deep.include({
91
+ 'view errors': 1,
92
+ 'collection: create': 1,
93
+ 'users: edit own': 1
94
+ })
95
+ })
96
+ })