expressa 2.0.17 → 2.0.18

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 (281) 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 +260 -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/support/commands.js +54 -54
  19. package/cypress/support/index.js +20 -20
  20. package/cypress/support/util.js +10 -10
  21. package/cypress.json +4 -4
  22. package/db/cached.js +40 -40
  23. package/db/file.js +112 -112
  24. package/db/memory.js +79 -79
  25. package/db/mongo.js +86 -86
  26. package/db/postgres.js +93 -93
  27. package/doc/authentication.md +38 -38
  28. package/doc/automatic-fields.md +12 -12
  29. package/doc/blogexample.md +16 -16
  30. package/doc/custom-endpoints.md +20 -20
  31. package/doc/database.md +23 -23
  32. package/doc/development.md +33 -33
  33. package/doc/listeners.md +103 -103
  34. package/doc/modules.md +8 -8
  35. package/doc/permissions.md +14 -14
  36. package/doc/relationships.md +65 -65
  37. package/doc/testing.md +47 -47
  38. package/doc/uploading-files.md +53 -53
  39. package/index.js +297 -297
  40. package/listeners.js +65 -65
  41. package/listeners_collection_permissions.js +29 -29
  42. package/listeners_users.js +96 -96
  43. package/listeners_validation.js +43 -43
  44. package/middleware/logging.js +30 -30
  45. package/middleware/permissions.js +41 -41
  46. package/modules/access_keys/access_keys.js +32 -32
  47. package/modules/admin/.babelrc +19 -19
  48. package/modules/admin/.editorconfig +14 -14
  49. package/modules/admin/.eslintignore +5 -5
  50. package/modules/admin/.eslintrc.js +197 -197
  51. package/modules/admin/.postcssrc.js +10 -10
  52. package/modules/admin/.travis.yml +5 -5
  53. package/modules/admin/LICENSE +21 -21
  54. package/modules/admin/README.md +88 -88
  55. package/modules/admin/build/build.js +45 -45
  56. package/modules/admin/build/check-versions.js +64 -64
  57. package/modules/admin/build/utils.js +108 -108
  58. package/modules/admin/build/vue-loader.conf.js +5 -5
  59. package/modules/admin/build/webpack.base.conf.js +112 -112
  60. package/modules/admin/build/webpack.dev.conf.js +95 -95
  61. package/modules/admin/build/webpack.prod.conf.js +112 -112
  62. package/modules/admin/config/dev.env.js +8 -8
  63. package/modules/admin/config/index.js +86 -86
  64. package/modules/admin/config/prod.env.js +5 -5
  65. package/modules/admin/dist/index.html +1 -1
  66. package/modules/admin/dist/index.html.gz +0 -0
  67. package/modules/admin/dist/static/css/app.9dd57eea.css +1 -0
  68. package/modules/admin/dist/static/css/app.9dd57eea.css.gz +0 -0
  69. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css +1 -0
  70. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css.gz +0 -0
  71. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css +1 -0
  72. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css.gz +0 -0
  73. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css +1 -0
  74. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css.gz +0 -0
  75. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css +1 -0
  76. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css.gz +0 -0
  77. package/modules/admin/dist/static/css/chunk-7291.13514e45.css +0 -0
  78. package/modules/admin/dist/static/css/chunk-7291.13514e45.css.gz +0 -0
  79. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css +1 -0
  80. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css.gz +0 -0
  81. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css +1 -0
  82. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css.gz +0 -0
  83. package/modules/admin/dist/static/css/chunk-b423.5f239333.css +0 -0
  84. package/modules/admin/dist/static/css/chunk-b423.5f239333.css.gz +0 -0
  85. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css +1 -0
  86. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css.gz +0 -0
  87. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css +1 -0
  88. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css.gz +0 -0
  89. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css +1 -0
  90. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css.gz +0 -0
  91. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css +1 -0
  92. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css.gz +0 -0
  93. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css +14 -0
  94. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css.gz +0 -0
  95. package/modules/admin/dist/static/fonts/element-icons.6f0a763.ttf +0 -0
  96. package/modules/admin/dist/static/js/app.e9461593.js +1 -0
  97. package/modules/admin/dist/static/js/app.e9461593.js.gz +0 -0
  98. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js +2 -0
  99. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt +13 -0
  100. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt.gz +0 -0
  101. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.gz +0 -0
  102. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js +1 -0
  103. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js.gz +0 -0
  104. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js +1 -0
  105. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js.gz +0 -0
  106. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js +1 -0
  107. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js.gz +0 -0
  108. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js +1 -0
  109. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js.gz +0 -0
  110. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js +1 -0
  111. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js.gz +0 -0
  112. package/modules/admin/dist/static/js/chunk-7291.590524e9.js +1 -0
  113. package/modules/admin/dist/static/js/chunk-7291.590524e9.js.gz +0 -0
  114. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js +1 -0
  115. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js.gz +0 -0
  116. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js +1 -0
  117. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js.gz +0 -0
  118. package/modules/admin/dist/static/js/chunk-b423.387c504c.js +1 -0
  119. package/modules/admin/dist/static/js/chunk-b423.387c504c.js.gz +0 -0
  120. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js +1 -0
  121. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js.gz +0 -0
  122. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js +1 -0
  123. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js.gz +0 -0
  124. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js +1 -0
  125. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js.gz +0 -0
  126. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js +1 -0
  127. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js.gz +0 -0
  128. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js +1 -0
  129. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js.gz +0 -0
  130. package/modules/admin/dist/static/js/chunk-libs.06c38828.js +2 -0
  131. package/modules/admin/dist/static/js/{app.981e71b3.js.LICENSE.txt → chunk-libs.06c38828.js.LICENSE.txt} +18 -15
  132. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.LICENSE.txt.gz +0 -0
  133. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.gz +0 -0
  134. package/modules/admin/index.html +16 -16
  135. package/modules/admin/package.json +101 -101
  136. package/modules/admin/src/App.vue +11 -11
  137. package/modules/admin/src/api/login.js +26 -26
  138. package/modules/admin/src/api/table.js +9 -9
  139. package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
  140. package/modules/admin/src/components/Hamburger/index.vue +62 -62
  141. package/modules/admin/src/components/JSONEditor.vue +180 -180
  142. package/modules/admin/src/components/SvgIcon/index.vue +43 -43
  143. package/modules/admin/src/icons/index.js +9 -9
  144. package/modules/admin/src/icons/svgo.yml +22 -22
  145. package/modules/admin/src/main.js +42 -42
  146. package/modules/admin/src/permission.js +49 -49
  147. package/modules/admin/src/router/index.js +200 -200
  148. package/modules/admin/src/store/getters.js +11 -11
  149. package/modules/admin/src/store/index.js +17 -17
  150. package/modules/admin/src/store/modules/app.js +43 -43
  151. package/modules/admin/src/store/modules/user.js +104 -104
  152. package/modules/admin/src/styles/element-ui.scss +29 -29
  153. package/modules/admin/src/styles/index.scss +78 -78
  154. package/modules/admin/src/styles/mixin.scss +27 -27
  155. package/modules/admin/src/styles/sidebar.scss +133 -133
  156. package/modules/admin/src/styles/transition.scss +46 -46
  157. package/modules/admin/src/styles/variables.scss +4 -4
  158. package/modules/admin/src/utils/auth.js +15 -15
  159. package/modules/admin/src/utils/index.js +74 -74
  160. package/modules/admin/src/utils/request.js +48 -48
  161. package/modules/admin/src/utils/validate.js +31 -31
  162. package/modules/admin/src/views/404.vue +235 -235
  163. package/modules/admin/src/views/Dev.vue +33 -33
  164. package/modules/admin/src/views/EditDocument.vue +116 -116
  165. package/modules/admin/src/views/Endpoints.vue +279 -279
  166. package/modules/admin/src/views/Home.vue +84 -84
  167. package/modules/admin/src/views/Install.vue +79 -79
  168. package/modules/admin/src/views/ListDocuments.vue +72 -72
  169. package/modules/admin/src/views/ListDocuments2.vue +462 -462
  170. package/modules/admin/src/views/ManageListeners.vue +67 -67
  171. package/modules/admin/src/views/ManageMiddleware.vue +43 -43
  172. package/modules/admin/src/views/ManagePermissions.vue +75 -75
  173. package/modules/admin/src/views/ViewRequest.vue +77 -77
  174. package/modules/admin/src/views/form/index.vue +91 -91
  175. package/modules/admin/src/views/layout/Layout.vue +69 -69
  176. package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
  177. package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
  178. package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
  179. package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
  180. package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
  181. package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
  182. package/modules/admin/src/views/layout/components/index.js +3 -3
  183. package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
  184. package/modules/admin/src/views/login/index.vue +195 -195
  185. package/modules/admin/src/views/tree/index.vue +77 -77
  186. package/modules/collections/collections.js +39 -39
  187. package/modules/core/core.js +197 -197
  188. package/modules/logging/logging.js +88 -88
  189. package/modules/permissions/permissions.js +106 -106
  190. package/package.json +59 -59
  191. package/scripts/expressa +12 -12
  192. package/scripts/run_cypress_tests.sh +5 -5
  193. package/scripts/run_db_tests.sh +8 -8
  194. package/test/0-install.js +96 -96
  195. package/test/collections.js +431 -431
  196. package/test/collections.querying.js +288 -288
  197. package/test/db.js +258 -258
  198. package/test/db.strings.js +73 -73
  199. package/test/db.updating.js +144 -144
  200. package/test/logging.js +29 -29
  201. package/test/test.js +93 -93
  202. package/test/testserver.js +17 -17
  203. package/test/testutils.js +136 -136
  204. package/test/users.js +425 -425
  205. package/util.js +522 -522
  206. package/modules/admin/dist/164c6167c1f3c497c07c.woff +0 -1
  207. package/modules/admin/dist/42ac07abc8473600c41f.ttf +0 -1
  208. package/modules/admin/dist/86dccb18a7eb4be8ef1a.woff +0 -1
  209. package/modules/admin/dist/c45297c558e0318fc9c5.ttf +0 -1
  210. package/modules/admin/dist/c717c9930715e24fa12c.woff +0 -1
  211. package/modules/admin/dist/ca6f07ef23f24cc2738a.ttf +0 -1
  212. package/modules/admin/dist/css/269.f7d5c7d5.css +0 -37
  213. package/modules/admin/dist/css/269.f7d5c7d5.css.gz +0 -0
  214. package/modules/admin/dist/css/451.c6646d20.css +0 -1
  215. package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
  216. package/modules/admin/dist/css/572.74d8e965.css +0 -34
  217. package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
  218. package/modules/admin/dist/css/651.e946bda7.css +0 -6
  219. package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
  220. package/modules/admin/dist/css/699.d1f90954.css +0 -8
  221. package/modules/admin/dist/css/699.d1f90954.css.gz +0 -0
  222. package/modules/admin/dist/css/750.4086915d.css +0 -2
  223. package/modules/admin/dist/css/750.4086915d.css.gz +0 -0
  224. package/modules/admin/dist/css/864.506917a4.css +0 -7
  225. package/modules/admin/dist/css/864.506917a4.css.gz +0 -0
  226. package/modules/admin/dist/css/899.506917a4.css +0 -7
  227. package/modules/admin/dist/css/899.506917a4.css.gz +0 -0
  228. package/modules/admin/dist/css/950.1fd9d57c.css +0 -7
  229. package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
  230. package/modules/admin/dist/css/app.11cc6245.css +0 -39
  231. package/modules/admin/dist/css/app.11cc6245.css.gz +0 -0
  232. package/modules/admin/dist/css/app.2e1b0d79.css +0 -591
  233. package/modules/admin/dist/css/app.2e1b0d79.css.gz +0 -0
  234. package/modules/admin/dist/css/app.4d43d0fd.css +0 -592
  235. package/modules/admin/dist/css/app.4d43d0fd.css.gz +0 -0
  236. package/modules/admin/dist/css/app.abace109.css +0 -1
  237. package/modules/admin/dist/css/app.abace109.css.gz +0 -0
  238. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css +0 -1
  239. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css.gz +0 -0
  240. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css +0 -1
  241. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css.gz +0 -0
  242. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css +0 -1
  243. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css.gz +0 -0
  244. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css +0 -1
  245. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css.gz +0 -0
  246. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css +0 -1
  247. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css.gz +0 -0
  248. package/modules/admin/dist/css/chunk-libs.de0d8484.css +0 -551
  249. package/modules/admin/dist/css/chunk-libs.de0d8484.css.gz +0 -0
  250. package/modules/admin/dist/static/fonts/element-icons.313f7da.woff +0 -0
  251. package/modules/admin/dist/static/fonts/element-icons.4520188.ttf +0 -0
  252. package/modules/admin/dist/static/js/269.7245ceaf.js +0 -1
  253. package/modules/admin/dist/static/js/269.7245ceaf.js.gz +0 -0
  254. package/modules/admin/dist/static/js/451.645974a8.js +0 -1
  255. package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
  256. package/modules/admin/dist/static/js/460.962d5bc0.js +0 -1
  257. package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
  258. package/modules/admin/dist/static/js/556.1e08866a.js +0 -1
  259. package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
  260. package/modules/admin/dist/static/js/572.13392e1d.js +0 -1
  261. package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
  262. package/modules/admin/dist/static/js/603.7b34a650.js +0 -1
  263. package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
  264. package/modules/admin/dist/static/js/637.26413baa.js +0 -1
  265. package/modules/admin/dist/static/js/637.26413baa.js.gz +0 -0
  266. package/modules/admin/dist/static/js/651.564b24b6.js +0 -1
  267. package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
  268. package/modules/admin/dist/static/js/653.02ec1098.js +0 -1
  269. package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
  270. package/modules/admin/dist/static/js/699.c7564884.js +0 -1
  271. package/modules/admin/dist/static/js/699.c7564884.js.gz +0 -0
  272. package/modules/admin/dist/static/js/750.50c950da.js +0 -1
  273. package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
  274. package/modules/admin/dist/static/js/864.4f43847d.js +0 -1
  275. package/modules/admin/dist/static/js/864.4f43847d.js.gz +0 -0
  276. package/modules/admin/dist/static/js/950.d4ff0a18.js +0 -1
  277. package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
  278. package/modules/admin/dist/static/js/app.981e71b3.js +0 -2
  279. package/modules/admin/dist/static/js/app.981e71b3.js.LICENSE.txt.gz +0 -0
  280. package/modules/admin/dist/static/js/app.981e71b3.js.gz +0 -0
  281. /package/modules/admin/dist/static/img/{404.4cf6930.png → 404.a57b6f3.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.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
- }
1
+ {
2
+ "name": "expressa",
3
+ "version": "2.0.18",
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
+ })