expressa 2.0.18 → 2.0.19

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 -260
  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/164c6167c1f3c497c07c.woff +1 -0
  66. package/modules/admin/dist/42ac07abc8473600c41f.ttf +1 -0
  67. package/modules/admin/dist/86dccb18a7eb4be8ef1a.woff +1 -0
  68. package/modules/admin/dist/c45297c558e0318fc9c5.ttf +1 -0
  69. package/modules/admin/dist/c717c9930715e24fa12c.woff +1 -0
  70. package/modules/admin/dist/ca6f07ef23f24cc2738a.ttf +1 -0
  71. package/modules/admin/dist/css/269.f7d5c7d5.css +37 -0
  72. package/modules/admin/dist/css/269.f7d5c7d5.css.gz +0 -0
  73. package/modules/admin/dist/css/451.c6646d20.css +1 -0
  74. package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
  75. package/modules/admin/dist/css/572.74d8e965.css +34 -0
  76. package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
  77. package/modules/admin/dist/css/651.e946bda7.css +6 -0
  78. package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
  79. package/modules/admin/dist/css/699.d1f90954.css +8 -0
  80. package/modules/admin/dist/css/699.d1f90954.css.gz +0 -0
  81. package/modules/admin/dist/css/750.4086915d.css +2 -0
  82. package/modules/admin/dist/css/750.4086915d.css.gz +0 -0
  83. package/modules/admin/dist/css/864.506917a4.css +7 -0
  84. package/modules/admin/dist/css/864.506917a4.css.gz +0 -0
  85. package/modules/admin/dist/css/899.506917a4.css +7 -0
  86. package/modules/admin/dist/css/899.506917a4.css.gz +0 -0
  87. package/modules/admin/dist/css/950.1fd9d57c.css +7 -0
  88. package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
  89. package/modules/admin/dist/css/app.11cc6245.css +39 -0
  90. package/modules/admin/dist/css/app.11cc6245.css.gz +0 -0
  91. package/modules/admin/dist/css/app.2e1b0d79.css +591 -0
  92. package/modules/admin/dist/css/app.2e1b0d79.css.gz +0 -0
  93. package/modules/admin/dist/css/app.4d43d0fd.css +592 -0
  94. package/modules/admin/dist/css/app.4d43d0fd.css.gz +0 -0
  95. package/modules/admin/dist/css/app.abace109.css +1 -0
  96. package/modules/admin/dist/css/app.abace109.css.gz +0 -0
  97. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css +1 -0
  98. package/modules/admin/dist/css/chunk-elementUI.67ad86d7.css.gz +0 -0
  99. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css +1 -0
  100. package/modules/admin/dist/css/chunk-elementUI.9e660bfd.css.gz +0 -0
  101. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css +1 -0
  102. package/modules/admin/dist/css/chunk-elementUI.c77cf142.css.gz +0 -0
  103. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css +1 -0
  104. package/modules/admin/dist/css/chunk-elementUI.f1625b35.css.gz +0 -0
  105. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css +1 -0
  106. package/modules/admin/dist/css/chunk-elementUI.f25dfb9b.css.gz +0 -0
  107. package/modules/admin/dist/css/chunk-libs.de0d8484.css +551 -0
  108. package/modules/admin/dist/css/chunk-libs.de0d8484.css.gz +0 -0
  109. package/modules/admin/dist/index.html +1 -1
  110. package/modules/admin/dist/static/fonts/element-icons.313f7da.woff +0 -0
  111. package/modules/admin/dist/static/fonts/element-icons.4520188.ttf +0 -0
  112. package/modules/admin/dist/static/js/269.7245ceaf.js +1 -0
  113. package/modules/admin/dist/static/js/269.7245ceaf.js.gz +0 -0
  114. package/modules/admin/dist/static/js/451.645974a8.js +1 -0
  115. package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
  116. package/modules/admin/dist/static/js/460.962d5bc0.js +1 -0
  117. package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
  118. package/modules/admin/dist/static/js/556.1e08866a.js +1 -0
  119. package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
  120. package/modules/admin/dist/static/js/572.13392e1d.js +1 -0
  121. package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
  122. package/modules/admin/dist/static/js/603.7b34a650.js +1 -0
  123. package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
  124. package/modules/admin/dist/static/js/637.26413baa.js +1 -0
  125. package/modules/admin/dist/static/js/637.26413baa.js.gz +0 -0
  126. package/modules/admin/dist/static/js/651.564b24b6.js +1 -0
  127. package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
  128. package/modules/admin/dist/static/js/653.02ec1098.js +1 -0
  129. package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
  130. package/modules/admin/dist/static/js/699.c7564884.js +1 -0
  131. package/modules/admin/dist/static/js/699.c7564884.js.gz +0 -0
  132. package/modules/admin/dist/static/js/750.50c950da.js +1 -0
  133. package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
  134. package/modules/admin/dist/static/js/864.4f43847d.js +1 -0
  135. package/modules/admin/dist/static/js/864.4f43847d.js.gz +0 -0
  136. package/modules/admin/dist/static/js/950.d4ff0a18.js +1 -0
  137. package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
  138. package/modules/admin/dist/static/js/app.981e71b3.js +2 -0
  139. package/modules/admin/dist/static/js/{chunk-libs.06c38828.js.LICENSE.txt → app.981e71b3.js.LICENSE.txt} +15 -18
  140. package/modules/admin/dist/static/js/app.981e71b3.js.LICENSE.txt.gz +0 -0
  141. package/modules/admin/dist/static/js/app.981e71b3.js.gz +0 -0
  142. package/modules/admin/index.html +16 -16
  143. package/modules/admin/package.json +101 -101
  144. package/modules/admin/src/App.vue +11 -11
  145. package/modules/admin/src/api/login.js +26 -26
  146. package/modules/admin/src/api/table.js +9 -9
  147. package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
  148. package/modules/admin/src/components/Hamburger/index.vue +62 -62
  149. package/modules/admin/src/components/JSONEditor.vue +180 -180
  150. package/modules/admin/src/components/SvgIcon/index.vue +43 -43
  151. package/modules/admin/src/icons/index.js +9 -9
  152. package/modules/admin/src/icons/svgo.yml +22 -22
  153. package/modules/admin/src/main.js +42 -42
  154. package/modules/admin/src/permission.js +49 -49
  155. package/modules/admin/src/router/index.js +200 -200
  156. package/modules/admin/src/store/getters.js +11 -11
  157. package/modules/admin/src/store/index.js +17 -17
  158. package/modules/admin/src/store/modules/app.js +43 -43
  159. package/modules/admin/src/store/modules/user.js +104 -104
  160. package/modules/admin/src/styles/element-ui.scss +29 -29
  161. package/modules/admin/src/styles/index.scss +78 -78
  162. package/modules/admin/src/styles/mixin.scss +27 -27
  163. package/modules/admin/src/styles/sidebar.scss +133 -133
  164. package/modules/admin/src/styles/transition.scss +46 -46
  165. package/modules/admin/src/styles/variables.scss +4 -4
  166. package/modules/admin/src/utils/auth.js +15 -15
  167. package/modules/admin/src/utils/index.js +74 -74
  168. package/modules/admin/src/utils/request.js +48 -48
  169. package/modules/admin/src/utils/validate.js +31 -31
  170. package/modules/admin/src/views/404.vue +235 -235
  171. package/modules/admin/src/views/Dev.vue +33 -33
  172. package/modules/admin/src/views/EditDocument.vue +116 -116
  173. package/modules/admin/src/views/Endpoints.vue +279 -279
  174. package/modules/admin/src/views/Home.vue +84 -84
  175. package/modules/admin/src/views/Install.vue +79 -79
  176. package/modules/admin/src/views/ListDocuments.vue +72 -72
  177. package/modules/admin/src/views/ListDocuments2.vue +462 -462
  178. package/modules/admin/src/views/ManageListeners.vue +67 -67
  179. package/modules/admin/src/views/ManageMiddleware.vue +43 -43
  180. package/modules/admin/src/views/ManagePermissions.vue +75 -75
  181. package/modules/admin/src/views/ViewRequest.vue +77 -77
  182. package/modules/admin/src/views/form/index.vue +91 -91
  183. package/modules/admin/src/views/layout/Layout.vue +69 -69
  184. package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
  185. package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
  186. package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
  187. package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
  188. package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
  189. package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
  190. package/modules/admin/src/views/layout/components/index.js +3 -3
  191. package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
  192. package/modules/admin/src/views/login/index.vue +195 -195
  193. package/modules/admin/src/views/tree/index.vue +77 -77
  194. package/modules/collections/collections.js +39 -39
  195. package/modules/core/core.js +197 -197
  196. package/modules/logging/logging.js +88 -88
  197. package/modules/permissions/permissions.js +106 -106
  198. package/package.json +59 -59
  199. package/scripts/expressa +12 -12
  200. package/scripts/run_cypress_tests.sh +5 -5
  201. package/scripts/run_db_tests.sh +8 -8
  202. package/test/0-install.js +96 -96
  203. package/test/collections.js +431 -431
  204. package/test/collections.querying.js +288 -288
  205. package/test/db.js +258 -258
  206. package/test/db.strings.js +73 -73
  207. package/test/db.updating.js +144 -144
  208. package/test/logging.js +29 -29
  209. package/test/test.js +93 -93
  210. package/test/testserver.js +17 -17
  211. package/test/testutils.js +136 -136
  212. package/test/users.js +425 -425
  213. package/util.js +522 -522
  214. package/modules/admin/dist/index.html.gz +0 -0
  215. package/modules/admin/dist/static/css/app.9dd57eea.css +0 -1
  216. package/modules/admin/dist/static/css/app.9dd57eea.css.gz +0 -0
  217. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css +0 -1
  218. package/modules/admin/dist/static/css/chunk-5061.ce0e4bdb.css.gz +0 -0
  219. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css +0 -1
  220. package/modules/admin/dist/static/css/chunk-5b97.7f9cb53e.css.gz +0 -0
  221. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css +0 -1
  222. package/modules/admin/dist/static/css/chunk-621e.b826be8d.css.gz +0 -0
  223. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css +0 -1
  224. package/modules/admin/dist/static/css/chunk-656b.9c828b00.css.gz +0 -0
  225. package/modules/admin/dist/static/css/chunk-7291.13514e45.css +0 -0
  226. package/modules/admin/dist/static/css/chunk-7291.13514e45.css.gz +0 -0
  227. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css +0 -1
  228. package/modules/admin/dist/static/css/chunk-7f29.9c828b00.css.gz +0 -0
  229. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css +0 -1
  230. package/modules/admin/dist/static/css/chunk-9a95.c647a2ef.css.gz +0 -0
  231. package/modules/admin/dist/static/css/chunk-b423.5f239333.css +0 -0
  232. package/modules/admin/dist/static/css/chunk-b423.5f239333.css.gz +0 -0
  233. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css +0 -1
  234. package/modules/admin/dist/static/css/chunk-bd5f.aefa49d7.css.gz +0 -0
  235. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css +0 -1
  236. package/modules/admin/dist/static/css/chunk-e374.025d58bb.css.gz +0 -0
  237. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css +0 -1
  238. package/modules/admin/dist/static/css/chunk-elementUI.3d004d9f.css.gz +0 -0
  239. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css +0 -1
  240. package/modules/admin/dist/static/css/chunk-f075.3a895a1e.css.gz +0 -0
  241. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css +0 -14
  242. package/modules/admin/dist/static/css/chunk-libs.327ad89e.css.gz +0 -0
  243. package/modules/admin/dist/static/fonts/element-icons.6f0a763.ttf +0 -0
  244. package/modules/admin/dist/static/js/app.e9461593.js +0 -1
  245. package/modules/admin/dist/static/js/app.e9461593.js.gz +0 -0
  246. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js +0 -2
  247. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt +0 -13
  248. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.LICENSE.txt.gz +0 -0
  249. package/modules/admin/dist/static/js/chunk-09d8.561880e0.js.gz +0 -0
  250. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js +0 -1
  251. package/modules/admin/dist/static/js/chunk-5061.83e6ccfa.js.gz +0 -0
  252. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js +0 -1
  253. package/modules/admin/dist/static/js/chunk-5b97.ac360086.js.gz +0 -0
  254. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js +0 -1
  255. package/modules/admin/dist/static/js/chunk-5e17.a2b69611.js.gz +0 -0
  256. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js +0 -1
  257. package/modules/admin/dist/static/js/chunk-621e.ccf42393.js.gz +0 -0
  258. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js +0 -1
  259. package/modules/admin/dist/static/js/chunk-656b.9d5b03c0.js.gz +0 -0
  260. package/modules/admin/dist/static/js/chunk-7291.590524e9.js +0 -1
  261. package/modules/admin/dist/static/js/chunk-7291.590524e9.js.gz +0 -0
  262. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js +0 -1
  263. package/modules/admin/dist/static/js/chunk-7f29.6ffc142e.js.gz +0 -0
  264. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js +0 -1
  265. package/modules/admin/dist/static/js/chunk-9a95.bdd76583.js.gz +0 -0
  266. package/modules/admin/dist/static/js/chunk-b423.387c504c.js +0 -1
  267. package/modules/admin/dist/static/js/chunk-b423.387c504c.js.gz +0 -0
  268. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js +0 -1
  269. package/modules/admin/dist/static/js/chunk-bd5f.e9509f10.js.gz +0 -0
  270. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js +0 -1
  271. package/modules/admin/dist/static/js/chunk-e374.7c87a0dd.js.gz +0 -0
  272. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js +0 -1
  273. package/modules/admin/dist/static/js/chunk-e7c3.e5df8ceb.js.gz +0 -0
  274. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js +0 -1
  275. package/modules/admin/dist/static/js/chunk-elementUI.b0c99c08.js.gz +0 -0
  276. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js +0 -1
  277. package/modules/admin/dist/static/js/chunk-f075.315ceec1.js.gz +0 -0
  278. package/modules/admin/dist/static/js/chunk-libs.06c38828.js +0 -2
  279. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.LICENSE.txt.gz +0 -0
  280. package/modules/admin/dist/static/js/chunk-libs.06c38828.js.gz +0 -0
  281. /package/modules/admin/dist/static/img/{404.a57b6f3.png → 404.4cf6930.png} +0 -0
@@ -1,105 +1,105 @@
1
- const util = require('../util')
2
-
3
- exports.updateAdminPermissions = async function (api) {
4
- if (!api.db.role) {
5
- return // not installed yet
6
- }
7
- const modules = Object.values(api.modules)
8
- const permissions = [].concat(...await Promise.all(modules.map((m) => util.resolve(m.permissions, api)))).filter(x => x !== undefined)
9
- let adminRole = { permissions: {} }
10
- try {
11
- adminRole = await api.db.role.get('Admin')
12
- } catch (e) {
13
- // expected if not installed
14
- }
15
- const neededPermissions = permissions.reduce((obj, p) => { obj[p] = 1; return obj }, {})
16
- adminRole.permissions = { ...neededPermissions, ...adminRole.permissions }
17
- await api.db.role.update('Admin', adminRole)
18
- }
19
-
20
- exports.install = async (req, api) => {
21
- const selectedModules = req.body.modules
22
- const installedModules = Object.keys(req.modules)
23
- const missingModules = selectedModules.filter((module) => !installedModules.includes(module))
24
- if (missingModules.length > 0) {
25
- throw new util.ApiError(400, 'unknown modules')
26
- }
27
-
28
- const modules = selectedModules.map((name) => req.modules[name])
29
-
30
- let settings = await api.db.settings.get(process.env.NODE_ENV).catch(() => {})
31
-
32
- if (!settings) {
33
- settings = JSON.parse(JSON.stringify(req.body.settings))
34
- settings._id = process.env.NODE_ENV
35
- settings.jwt_secret = util.createSecureRandomId()
36
- // Remove fields that are not real settings
37
- delete settings.email
38
- delete settings.user_storage
39
- delete settings.password
40
- Object.assign(req.settings, settings)
41
- await req.db.settings.create(settings)
42
-
43
- for (const m of modules) {
44
- const colls = await util.resolve(m.collections, api)
45
- if (colls) {
46
- for (const coll of colls) {
47
- if (!coll.storage) {
48
- coll.storage = 'file'
49
- }
50
- if (coll._id == 'users') {
51
- if (req.body.settings.user_storage) {
52
- coll.storage = req.body.settings.user_storage
53
- }
54
- coll.enableLogin = true
55
- }
56
- await req.db.collection.create(coll)
57
- await api.notify('changed', req, 'collection', coll)
58
- // await collectionsApi.insert(Object.assign({}, req, { body: coll }))
59
- }
60
- }
61
- await util.resolve(m.install, api)
62
- }
63
- await exports.updateAdminPermissions(api)
64
- }
65
- else {
66
- if (settings.installed) {
67
- throw new Error(`${process.env.NODE_ENV}.json exists and indicates expressa is already installed. Try setting 'installed' to false if you are attempting to reinstall.`)
68
- }
69
- }
70
-
71
- settings.installed = true
72
- settings.enforce_permissions = true
73
- Object.assign(req.settings, settings)
74
- await req.db.settings.update(settings._id, settings)
75
- return { }
76
- }
77
-
78
- exports.getSettingsSchema = async (req, api) => {
79
- const colls = await util.resolve(api.modules.core.collections, api)
80
- const settings = colls.find((m) => m._id === 'settings')
81
- settings.schema.properties = {
82
- /*collection_storage: {
83
- type: 'string',
84
- enum: ['file', 'mongo', 'postgres']
85
- },*/
86
- user_storage: {
87
- type: 'string',
88
- enum: ['file', 'mongo', 'postgres']
89
- },
90
- email: {
91
- type: 'string',
92
- description: 'Administrator Email'
93
- },
94
- password: {
95
- type: 'string',
96
- description: 'Administrator Password'
97
- },
98
- ...settings.schema.properties
99
- }
100
- settings.schema.required = settings.schema.required || ['postgresql_uri', 'mongodb_uri']
101
- settings.schema.required.push('email')
102
- settings.schema.required.push('password')
103
- settings.schema.required.push('user_storage')
104
- return settings
105
- }
1
+ const util = require('../util')
2
+
3
+ exports.updateAdminPermissions = async function (api) {
4
+ if (!api.db.role) {
5
+ return // not installed yet
6
+ }
7
+ const modules = Object.values(api.modules)
8
+ const permissions = [].concat(...await Promise.all(modules.map((m) => util.resolve(m.permissions, api)))).filter(x => x !== undefined)
9
+ let adminRole = { permissions: {} }
10
+ try {
11
+ adminRole = await api.db.role.get('Admin')
12
+ } catch (e) {
13
+ // expected if not installed
14
+ }
15
+ const neededPermissions = permissions.reduce((obj, p) => { obj[p] = 1; return obj }, {})
16
+ adminRole.permissions = { ...neededPermissions, ...adminRole.permissions }
17
+ await api.db.role.update('Admin', adminRole)
18
+ }
19
+
20
+ exports.install = async (req, api) => {
21
+ const selectedModules = req.body.modules
22
+ const installedModules = Object.keys(req.modules)
23
+ const missingModules = selectedModules.filter((module) => !installedModules.includes(module))
24
+ if (missingModules.length > 0) {
25
+ throw new util.ApiError(400, 'unknown modules')
26
+ }
27
+
28
+ const modules = selectedModules.map((name) => req.modules[name])
29
+
30
+ let settings = await api.db.settings.get(process.env.NODE_ENV).catch(() => {})
31
+
32
+ if (!settings) {
33
+ settings = JSON.parse(JSON.stringify(req.body.settings))
34
+ settings._id = process.env.NODE_ENV
35
+ settings.jwt_secret = util.createSecureRandomId()
36
+ // Remove fields that are not real settings
37
+ delete settings.email
38
+ delete settings.user_storage
39
+ delete settings.password
40
+ Object.assign(req.settings, settings)
41
+ await req.db.settings.create(settings)
42
+
43
+ for (const m of modules) {
44
+ const colls = await util.resolve(m.collections, api)
45
+ if (colls) {
46
+ for (const coll of colls) {
47
+ if (!coll.storage) {
48
+ coll.storage = 'file'
49
+ }
50
+ if (coll._id == 'users') {
51
+ if (req.body.settings.user_storage) {
52
+ coll.storage = req.body.settings.user_storage
53
+ }
54
+ coll.enableLogin = true
55
+ }
56
+ await req.db.collection.create(coll)
57
+ await api.notify('changed', req, 'collection', coll)
58
+ // await collectionsApi.insert(Object.assign({}, req, { body: coll }))
59
+ }
60
+ }
61
+ await util.resolve(m.install, api)
62
+ }
63
+ await exports.updateAdminPermissions(api)
64
+ }
65
+ else {
66
+ if (settings.installed) {
67
+ throw new Error(`${process.env.NODE_ENV}.json exists and indicates expressa is already installed. Try setting 'installed' to false if you are attempting to reinstall.`)
68
+ }
69
+ }
70
+
71
+ settings.installed = true
72
+ settings.enforce_permissions = true
73
+ Object.assign(req.settings, settings)
74
+ await req.db.settings.update(settings._id, settings)
75
+ return { }
76
+ }
77
+
78
+ exports.getSettingsSchema = async (req, api) => {
79
+ const colls = await util.resolve(api.modules.core.collections, api)
80
+ const settings = colls.find((m) => m._id === 'settings')
81
+ settings.schema.properties = {
82
+ /*collection_storage: {
83
+ type: 'string',
84
+ enum: ['file', 'mongo', 'postgres']
85
+ },*/
86
+ user_storage: {
87
+ type: 'string',
88
+ enum: ['file', 'mongo', 'postgres']
89
+ },
90
+ email: {
91
+ type: 'string',
92
+ description: 'Administrator Email'
93
+ },
94
+ password: {
95
+ type: 'string',
96
+ description: 'Administrator Password'
97
+ },
98
+ ...settings.schema.properties
99
+ }
100
+ settings.schema.required = settings.schema.required || ['postgresql_uri', 'mongodb_uri']
101
+ settings.schema.required.push('email')
102
+ settings.schema.required.push('password')
103
+ settings.schema.required.push('user_storage')
104
+ return settings
105
+ }
@@ -1,43 +1,43 @@
1
- const util = require('../util')
2
-
3
- exports.getStatus = function(router) {
4
- return async (req) => {
5
- if (!req.hasPermission('view server details')) {
6
- return {
7
- env: process.env.NODE_ENV,
8
- installed: req.settings.installed || false,
9
- }
10
- }
11
- const allListeners = [].concat.apply([], Object.values(req.eventListeners))
12
- const middleware = router.stack.filter((item) => !item.route).map((item) => ({
13
- name: item.name,
14
- params: util.getFunctionParamNames(item.handle),
15
- }))
16
- const uniqueListeners = [...new Set(allListeners)]
17
- const eventTypes = ['get', 'post', 'put', 'delete', 'changed', 'deleted']
18
- const listeners = uniqueListeners.map(function (listener) {
19
- const o = {}
20
- o.name = listener.name
21
- o.priority = listener.priority
22
- o.collections = listener.collections
23
- for (const type of eventTypes) {
24
- if (router.eventListeners[type].includes(listener)) {
25
- o[type] = true
26
- }
27
- }
28
- return o
29
- })
30
- listeners.sort((a, b) => a.priority - b.priority)
31
- const collections = Object.keys(router.db)
32
- .filter((collection) => req.hasPermission(`${collection}: view`) || req.hasPermission(`${collection}: view own`))
33
- return {
34
- nodeVersion: process.version,
35
- uptime: util.friendlyDuration(process.uptime()),
36
- env: process.env.NODE_ENV,
37
- installed: req.settings.installed || false,
38
- middleware,
39
- listeners,
40
- collections,
41
- }
42
- }
43
- }
1
+ const util = require('../util')
2
+
3
+ exports.getStatus = function(router) {
4
+ return async (req) => {
5
+ if (!req.hasPermission('view server details')) {
6
+ return {
7
+ env: process.env.NODE_ENV,
8
+ installed: req.settings.installed || false,
9
+ }
10
+ }
11
+ const allListeners = [].concat.apply([], Object.values(req.eventListeners))
12
+ const middleware = router.stack.filter((item) => !item.route).map((item) => ({
13
+ name: item.name,
14
+ params: util.getFunctionParamNames(item.handle),
15
+ }))
16
+ const uniqueListeners = [...new Set(allListeners)]
17
+ const eventTypes = ['get', 'post', 'put', 'delete', 'changed', 'deleted']
18
+ const listeners = uniqueListeners.map(function (listener) {
19
+ const o = {}
20
+ o.name = listener.name
21
+ o.priority = listener.priority
22
+ o.collections = listener.collections
23
+ for (const type of eventTypes) {
24
+ if (router.eventListeners[type].includes(listener)) {
25
+ o[type] = true
26
+ }
27
+ }
28
+ return o
29
+ })
30
+ listeners.sort((a, b) => a.priority - b.priority)
31
+ const collections = Object.keys(router.db)
32
+ .filter((collection) => req.hasPermission(`${collection}: view`) || req.hasPermission(`${collection}: view own`))
33
+ return {
34
+ nodeVersion: process.version,
35
+ uptime: util.friendlyDuration(process.uptime()),
36
+ env: process.env.NODE_ENV,
37
+ installed: req.settings.installed || false,
38
+ middleware,
39
+ listeners,
40
+ collections,
41
+ }
42
+ }
43
+ }
@@ -1,52 +1,52 @@
1
- const auth = require('../auth')
2
- const util = require('../util')
3
- const collectionsApi = require('./collections')
4
- const permissions = require('../middleware/permissions')
5
-
6
- exports.login = async (req, collection) => {
7
- const password = req.body.password
8
-
9
- if (typeof req.body.email !== 'string') {
10
- throw new util.ApiError(400, 'email must be a string')
11
- }
12
-
13
- req.body.email = req.body.email.toLowerCase()
14
-
15
- // check if user exists
16
- const result = await req.db[collection].find({
17
- email: req.body.email
18
- })
19
- if (result.length === 0) {
20
- throw new util.ApiError(400, 'No ' + collection + ' found with this email.')
21
- }
22
- const user = result[0]
23
- if (!auth.isValidPassword(password, user.password)) {
24
- throw new util.ApiError(401, 'Incorrect password')
25
- }
26
- const jwt_options = req.settings.jwt_expires_in ? { expiresIn: req.settings.jwt_expires_in } : {}
27
- const payload = auth.doLogin({
28
- id: user._id,
29
- collection,
30
- timestamp: user.meta.password_last_updated_at,
31
- jwt_secret: req.getSetting('jwt_secret'),
32
- jwt_options
33
- })
34
- req.uid = user._id
35
- req.ucollection = collection
36
- req.user = user
37
- await permissions.addRolePermissionsAsync(req)
38
- payload.canUseAdmin = req.hasPermission('login to admin')
39
- return payload
40
- }
41
-
42
- exports.register = function (req, collection) {
43
- req.url = `/${collection}`
44
- req.params.collection = collection
45
- return collectionsApi.insert(req)
46
- }
47
-
48
- exports.getMe = function (req, collection) {
49
- req.params.collection = collection
50
- req.params.id = req.uid
51
- return collectionsApi.getById(req)
52
- }
1
+ const auth = require('../auth')
2
+ const util = require('../util')
3
+ const collectionsApi = require('./collections')
4
+ const permissions = require('../middleware/permissions')
5
+
6
+ exports.login = async (req, collection) => {
7
+ const password = req.body.password
8
+
9
+ if (typeof req.body.email !== 'string') {
10
+ throw new util.ApiError(400, 'email must be a string')
11
+ }
12
+
13
+ req.body.email = req.body.email.toLowerCase()
14
+
15
+ // check if user exists
16
+ const result = await req.db[collection].find({
17
+ email: req.body.email
18
+ })
19
+ if (result.length === 0) {
20
+ throw new util.ApiError(400, 'No ' + collection + ' found with this email.')
21
+ }
22
+ const user = result[0]
23
+ if (!auth.isValidPassword(password, user.password)) {
24
+ throw new util.ApiError(401, 'Incorrect password')
25
+ }
26
+ const jwt_options = req.settings.jwt_expires_in ? { expiresIn: req.settings.jwt_expires_in } : {}
27
+ const payload = auth.doLogin({
28
+ id: user._id,
29
+ collection,
30
+ timestamp: user.meta.password_last_updated_at,
31
+ jwt_secret: req.getSetting('jwt_secret'),
32
+ jwt_options
33
+ })
34
+ req.uid = user._id
35
+ req.ucollection = collection
36
+ req.user = user
37
+ await permissions.addRolePermissionsAsync(req)
38
+ payload.canUseAdmin = req.hasPermission('login to admin')
39
+ return payload
40
+ }
41
+
42
+ exports.register = function (req, collection) {
43
+ req.url = `/${collection}`
44
+ req.params.collection = collection
45
+ return collectionsApi.insert(req)
46
+ }
47
+
48
+ exports.getMe = function (req, collection) {
49
+ req.params.collection = collection
50
+ req.params.id = req.uid
51
+ return collectionsApi.getById(req)
52
+ }
@@ -1,5 +1,5 @@
1
- {
2
- "name": "Using fixtures to represent data",
3
- "email": "hello@cypress.io",
4
- "body": "Fixtures are a great way to mock data for responses to routes"
1
+ {
2
+ "name": "Using fixtures to represent data",
3
+ "email": "hello@cypress.io",
4
+ "body": "Fixtures are a great way to mock data for responses to routes"
5
5
  }
@@ -1,9 +1,9 @@
1
- describe('Install', function() {
2
- it('Creates a user', function() {
3
- cy.visit('/')
4
- cy.get('input[name="root[email]"]').type('test@example.com')
5
- cy.get('input[name="root[password]"]').type('expressa')
6
- cy.get('.btn-primary').click()
7
- cy.contains('Welcome: test@example.com')
8
- })
1
+ describe('Install', function() {
2
+ it('Creates a user', function() {
3
+ cy.visit('/')
4
+ cy.get('input[name="root[email]"]').type('test@example.com')
5
+ cy.get('input[name="root[password]"]').type('expressa')
6
+ cy.get('.btn-primary').click()
7
+ cy.contains('Welcome: test@example.com')
8
+ })
9
9
  })
@@ -1,29 +1,29 @@
1
- import { randomId } from '../support/util'
2
-
3
- // TODO: remove error from JSONSchemaEditor so that this isn't necessary
4
- Cypress.on('uncaught:exception', (err, runnable) => {
5
- // returning false here prevents Cypress from
6
- // failing the test
7
- return false
8
- })
9
-
10
- describe('Custom Collections', function() {
11
- it('Supports creating new collections', function() {
12
- cy.login()
13
- cy.visit('/')
14
- cy.get('.hamburger-container').click();
15
- cy.wait(100)
16
- cy.get('span').contains('Collection').click();
17
-
18
- cy.get('.btn-primary').click();
19
- let id = `coll-${randomId()}`;
20
- cy.fillValue('_id', id)
21
-
22
- cy.wait(100)
23
- cy.get('button').contains('Add another field').click();
24
- cy.wait(100)
25
- cy.get('input[name="field"]').type('field_1')
26
-
27
- cy.get('.btn-primary').click();
28
- })
1
+ import { randomId } from '../support/util'
2
+
3
+ // TODO: remove error from JSONSchemaEditor so that this isn't necessary
4
+ Cypress.on('uncaught:exception', (err, runnable) => {
5
+ // returning false here prevents Cypress from
6
+ // failing the test
7
+ return false
8
+ })
9
+
10
+ describe('Custom Collections', function() {
11
+ it('Supports creating new collections', function() {
12
+ cy.login()
13
+ cy.visit('/')
14
+ cy.get('.hamburger-container').click();
15
+ cy.wait(100)
16
+ cy.get('span').contains('Collection').click();
17
+
18
+ cy.get('.btn-primary').click();
19
+ let id = `coll-${randomId()}`;
20
+ cy.fillValue('_id', id)
21
+
22
+ cy.wait(100)
23
+ cy.get('button').contains('Add another field').click();
24
+ cy.wait(100)
25
+ cy.get('input[name="field"]').type('field_1')
26
+
27
+ cy.get('.btn-primary').click();
28
+ })
29
29
  })
@@ -1,9 +1,9 @@
1
- describe('Home', function() {
2
- it('Logs and shows 404s', function() {
3
- cy.request({ url: 'http://localhost:3001/api/notexist', failOnStatusCode: false })
4
- cy.login()
5
- cy.visit('/')
6
- cy.get('.el-table__body').contains('notexist')
7
- cy.get('.el-table__body').contains('404')
8
- })
9
- })
1
+ describe('Home', function() {
2
+ it('Logs and shows 404s', function() {
3
+ cy.request({ url: 'http://localhost:3001/api/notexist', failOnStatusCode: false })
4
+ cy.login()
5
+ cy.visit('/')
6
+ cy.get('.el-table__body').contains('notexist')
7
+ cy.get('.el-table__body').contains('404')
8
+ })
9
+ })
@@ -1,34 +1,34 @@
1
- describe('Settings', function() {
2
- it('Can turn off enforce permissions', function() {
3
- cy.request({ url: 'http://localhost:3001/api/role/Admin', failOnStatusCode: false })
4
- .then((response) => {
5
- expect(response.status).to.equal(401)
6
- });
7
-
8
- cy.login()
9
- cy.visit('/')
10
-
11
- cy.wait(250)
12
- cy.get('a').contains('(edit settings)').click()
13
- cy.wait(1500)
14
-
15
- cy.get('[name="root[enforce_permissions]"]').uncheck()
16
- cy.get('button.btn-primary').click()
17
- })
18
-
19
- it('Changed settings should take affect', function() {
20
- cy.request({url: 'http://localhost:3001/api/role/Admin', failOnStatusCode: false})
21
- })
22
-
23
- it('Turn back on enforce permissions', function() {
24
- cy.login()
25
- cy.visit('/')
26
-
27
- cy.wait(250)
28
- cy.get('a').contains('(edit settings)').click()
29
- cy.wait(1500)
30
-
31
- cy.get('[name="root[enforce_permissions]"]').check()
32
- cy.get('button.btn-primary').click()
33
- })
34
- })
1
+ describe('Settings', function() {
2
+ it('Can turn off enforce permissions', function() {
3
+ cy.request({ url: 'http://localhost:3001/api/role/Admin', failOnStatusCode: false })
4
+ .then((response) => {
5
+ expect(response.status).to.equal(401)
6
+ });
7
+
8
+ cy.login()
9
+ cy.visit('/')
10
+
11
+ cy.wait(250)
12
+ cy.get('a').contains('(edit settings)').click()
13
+ cy.wait(1500)
14
+
15
+ cy.get('[name="root[enforce_permissions]"]').uncheck()
16
+ cy.get('button.btn-primary').click()
17
+ })
18
+
19
+ it('Changed settings should take affect', function() {
20
+ cy.request({url: 'http://localhost:3001/api/role/Admin', failOnStatusCode: false})
21
+ })
22
+
23
+ it('Turn back on enforce permissions', function() {
24
+ cy.login()
25
+ cy.visit('/')
26
+
27
+ cy.wait(250)
28
+ cy.get('a').contains('(edit settings)').click()
29
+ cy.wait(1500)
30
+
31
+ cy.get('[name="root[enforce_permissions]"]').check()
32
+ cy.get('button.btn-primary').click()
33
+ })
34
+ })