expressa 2.0.20 → 2.0.22

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 (230) hide show
  1. package/.circleci/config.yml +21 -21
  2. package/.eslintrc.json +29 -29
  3. package/.vscode/launch.json +19 -0
  4. package/LICENSE +21 -21
  5. package/README.md +137 -137
  6. package/auth/index.js +76 -76
  7. package/auth/jwt.js +31 -31
  8. package/controllers/collections.js +260 -260
  9. package/controllers/install.js +105 -105
  10. package/controllers/status.js +43 -43
  11. package/controllers/users.js +52 -52
  12. package/cypress/fixtures/example.json +4 -4
  13. package/cypress/integration/0_install_spec.js +8 -8
  14. package/cypress/integration/custom_collections.js +30 -30
  15. package/cypress/integration/home.js +9 -9
  16. package/cypress/integration/settings.js +34 -34
  17. package/cypress/integration/users.js +61 -61
  18. package/cypress/plugins/index.js +17 -17
  19. package/cypress/support/commands.js +69 -69
  20. package/cypress/support/index.js +20 -20
  21. package/cypress/support/util.js +10 -10
  22. package/cypress.config.js +18 -18
  23. package/cypress.json +4 -4
  24. package/db/cached.js +44 -40
  25. package/db/file.js +131 -112
  26. package/db/memory.js +92 -79
  27. package/db/mongo.js +93 -86
  28. package/db/postgres.js +100 -93
  29. package/doc/authentication.md +38 -38
  30. package/doc/automatic-fields.md +12 -12
  31. package/doc/blogexample.md +16 -16
  32. package/doc/custom-endpoints.md +20 -20
  33. package/doc/database.md +23 -23
  34. package/doc/development.md +33 -33
  35. package/doc/listeners.md +103 -103
  36. package/doc/modules.md +8 -8
  37. package/doc/permissions.md +14 -14
  38. package/doc/relationships.md +65 -65
  39. package/doc/testing.md +47 -47
  40. package/doc/uploading-files.md +53 -53
  41. package/index.js +297 -297
  42. package/listeners.js +65 -65
  43. package/listeners_collection_permissions.js +29 -29
  44. package/listeners_users.js +96 -96
  45. package/listeners_validation.js +43 -43
  46. package/middleware/logging.js +30 -30
  47. package/middleware/permissions.js +41 -41
  48. package/modules/access_keys/access_keys.js +32 -32
  49. package/modules/admin/.babelrc +19 -19
  50. package/modules/admin/.editorconfig +14 -14
  51. package/modules/admin/.eslintignore +5 -5
  52. package/modules/admin/.eslintrc.js +197 -197
  53. package/modules/admin/.postcssrc.js +10 -10
  54. package/modules/admin/.travis.yml +5 -5
  55. package/modules/admin/LICENSE +21 -21
  56. package/modules/admin/README.md +88 -88
  57. package/modules/admin/build/build.js +46 -46
  58. package/modules/admin/build/check-versions.js +64 -64
  59. package/modules/admin/build/utils.js +109 -109
  60. package/modules/admin/build/vue-loader.conf.js +5 -5
  61. package/modules/admin/build/webpack.base.conf.js +112 -112
  62. package/modules/admin/build/webpack.dev.conf.js +95 -95
  63. package/modules/admin/build/webpack.prod.conf.js +112 -112
  64. package/modules/admin/config/dev.env.js +8 -8
  65. package/modules/admin/config/index.js +86 -86
  66. package/modules/admin/config/prod.env.js +5 -5
  67. package/modules/admin/dist/css/136.1055b646.css +69 -0
  68. package/modules/admin/dist/css/136.1055b646.css.gz +0 -0
  69. package/modules/admin/dist/css/{430.8c9b0482.css → 165.e83d8cfe.css} +4 -4
  70. package/modules/admin/dist/css/165.e83d8cfe.css.gz +0 -0
  71. package/modules/admin/dist/css/220.e946bda7.css.gz +0 -0
  72. package/modules/admin/dist/css/{197.7a90435e.css → 236.e66ce8d8.css} +4 -4
  73. package/modules/admin/dist/css/236.e66ce8d8.css.gz +0 -0
  74. package/modules/admin/dist/css/338.1fd9d57c.css.gz +0 -0
  75. package/modules/admin/dist/css/{566.7a90435e.css → 566.e66ce8d8.css} +4 -4
  76. package/modules/admin/dist/css/566.e66ce8d8.css.gz +0 -0
  77. package/modules/admin/dist/css/76.46fe6799.css +66 -0
  78. package/modules/admin/dist/css/76.46fe6799.css.gz +0 -0
  79. package/modules/admin/dist/css/807.f450521e.css +1 -0
  80. package/modules/admin/dist/css/807.f450521e.css.gz +0 -0
  81. package/modules/admin/dist/css/{750.4086915d.css.gz → 913.4086915d.css.gz} +0 -0
  82. package/modules/admin/dist/css/{app.eba5f5e2.css → app.1c3232a3.css} +25 -25
  83. package/modules/admin/dist/css/app.1c3232a3.css.gz +0 -0
  84. package/modules/admin/dist/index.html +1 -1
  85. package/modules/admin/dist/static/js/115.108d0dd5.js +1 -0
  86. package/modules/admin/dist/static/js/115.108d0dd5.js.gz +0 -0
  87. package/modules/admin/dist/static/js/136.1f9f4cb0.js +1 -0
  88. package/modules/admin/dist/static/js/136.1f9f4cb0.js.gz +0 -0
  89. package/modules/admin/dist/static/js/165.b3d51941.js +1 -0
  90. package/modules/admin/dist/static/js/165.b3d51941.js.gz +0 -0
  91. package/modules/admin/dist/static/js/220.02b2cd49.js +1 -0
  92. package/modules/admin/dist/static/js/220.02b2cd49.js.gz +0 -0
  93. package/modules/admin/dist/static/js/236.98c79868.js +1 -0
  94. package/modules/admin/dist/static/js/236.98c79868.js.gz +0 -0
  95. package/modules/admin/dist/static/js/338.4ba49501.js +1 -0
  96. package/modules/admin/dist/static/js/338.4ba49501.js.gz +0 -0
  97. package/modules/admin/dist/static/js/381.a05421de.js +1 -0
  98. package/modules/admin/dist/static/js/381.a05421de.js.gz +0 -0
  99. package/modules/admin/dist/static/js/412.0914ff23.js +1 -0
  100. package/modules/admin/dist/static/js/412.0914ff23.js.gz +0 -0
  101. package/modules/admin/dist/static/js/533.507df4cb.js +1 -0
  102. package/modules/admin/dist/static/js/533.507df4cb.js.gz +0 -0
  103. package/modules/admin/dist/static/js/556.d7586b89.js +1 -0
  104. package/modules/admin/dist/static/js/556.d7586b89.js.gz +0 -0
  105. package/modules/admin/dist/static/js/76.811d0e96.js +1 -0
  106. package/modules/admin/dist/static/js/76.811d0e96.js.gz +0 -0
  107. package/modules/admin/dist/static/js/807.8b7455a7.js +1 -0
  108. package/modules/admin/dist/static/js/807.8b7455a7.js.gz +0 -0
  109. package/modules/admin/dist/static/js/913.8b376386.js +1 -0
  110. package/modules/admin/dist/static/js/913.8b376386.js.gz +0 -0
  111. package/modules/admin/dist/static/js/app.834abee4.js +2 -0
  112. package/modules/admin/dist/static/js/{app.ea86ae11.js.LICENSE.txt → app.834abee4.js.LICENSE.txt} +3 -3
  113. package/modules/admin/dist/static/js/app.834abee4.js.LICENSE.txt.gz +0 -0
  114. package/modules/admin/dist/static/js/app.834abee4.js.gz +0 -0
  115. package/modules/admin/index.html +16 -16
  116. package/modules/admin/package.json +102 -101
  117. package/modules/admin/src/App.vue +11 -11
  118. package/modules/admin/src/api/login.js +26 -26
  119. package/modules/admin/src/api/table.js +9 -9
  120. package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
  121. package/modules/admin/src/components/Hamburger/index.vue +62 -62
  122. package/modules/admin/src/components/JSONEditor.vue +206 -180
  123. package/modules/admin/src/components/SvgIcon/index.vue +43 -43
  124. package/modules/admin/src/icons/index.js +9 -9
  125. package/modules/admin/src/icons/svgo.yml +22 -22
  126. package/modules/admin/src/main.js +42 -42
  127. package/modules/admin/src/permission.js +49 -49
  128. package/modules/admin/src/router/index.js +200 -200
  129. package/modules/admin/src/store/getters.js +11 -11
  130. package/modules/admin/src/store/index.js +17 -17
  131. package/modules/admin/src/store/modules/app.js +43 -43
  132. package/modules/admin/src/store/modules/user.js +104 -104
  133. package/modules/admin/src/styles/element-ui.scss +29 -29
  134. package/modules/admin/src/styles/index.scss +78 -78
  135. package/modules/admin/src/styles/mixin.scss +27 -27
  136. package/modules/admin/src/styles/sidebar.scss +133 -133
  137. package/modules/admin/src/styles/transition.scss +46 -46
  138. package/modules/admin/src/styles/variables.scss +4 -4
  139. package/modules/admin/src/utils/auth.js +15 -15
  140. package/modules/admin/src/utils/index.js +74 -74
  141. package/modules/admin/src/utils/request.js +47 -48
  142. package/modules/admin/src/utils/validate.js +31 -31
  143. package/modules/admin/src/views/404.vue +235 -235
  144. package/modules/admin/src/views/Dev.vue +33 -33
  145. package/modules/admin/src/views/EditDocument.vue +121 -121
  146. package/modules/admin/src/views/Endpoints.vue +279 -279
  147. package/modules/admin/src/views/Home.vue +84 -84
  148. package/modules/admin/src/views/Install.vue +79 -79
  149. package/modules/admin/src/views/ListDocuments.vue +72 -72
  150. package/modules/admin/src/views/ListDocuments2.vue +467 -467
  151. package/modules/admin/src/views/ManageListeners.vue +67 -67
  152. package/modules/admin/src/views/ManageMiddleware.vue +43 -43
  153. package/modules/admin/src/views/ManagePermissions.vue +75 -75
  154. package/modules/admin/src/views/ViewRequest.vue +77 -77
  155. package/modules/admin/src/views/form/index.vue +91 -91
  156. package/modules/admin/src/views/layout/Layout.vue +69 -69
  157. package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
  158. package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
  159. package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
  160. package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
  161. package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
  162. package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
  163. package/modules/admin/src/views/layout/components/index.js +3 -3
  164. package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
  165. package/modules/admin/src/views/login/index.vue +195 -195
  166. package/modules/admin/src/views/tree/index.vue +77 -77
  167. package/modules/collections/collections.js +39 -39
  168. package/modules/core/core.js +197 -197
  169. package/modules/logging/logging.js +88 -88
  170. package/modules/permissions/permissions.js +106 -106
  171. package/package.json +59 -59
  172. package/scripts/expressa +12 -12
  173. package/scripts/run_cypress_tests.sh +35 -35
  174. package/scripts/run_db_tests.sh +8 -8
  175. package/test/0-install.js +96 -96
  176. package/test/collections.js +431 -431
  177. package/test/collections.querying.js +288 -288
  178. package/test/db.js +258 -258
  179. package/test/db.strings.js +73 -73
  180. package/test/db.updating.js +186 -144
  181. package/test/logging.js +29 -29
  182. package/test/test.js +93 -93
  183. package/test/testserver.js +30 -17
  184. package/test/testutils.js +136 -136
  185. package/test/users.js +425 -425
  186. package/util.js +522 -522
  187. package/modules/admin/dist/css/197.7a90435e.css.gz +0 -0
  188. package/modules/admin/dist/css/430.8c9b0482.css.gz +0 -0
  189. package/modules/admin/dist/css/451.c6646d20.css +0 -1
  190. package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
  191. package/modules/admin/dist/css/566.7a90435e.css.gz +0 -0
  192. package/modules/admin/dist/css/569.f7d5c7d5.css +0 -37
  193. package/modules/admin/dist/css/569.f7d5c7d5.css.gz +0 -0
  194. package/modules/admin/dist/css/572.74d8e965.css +0 -34
  195. package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
  196. package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
  197. package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
  198. package/modules/admin/dist/css/app.eba5f5e2.css.gz +0 -0
  199. package/modules/admin/dist/static/js/197.e511d91e.js +0 -1
  200. package/modules/admin/dist/static/js/197.e511d91e.js.gz +0 -0
  201. package/modules/admin/dist/static/js/430.b3941f30.js +0 -1
  202. package/modules/admin/dist/static/js/430.b3941f30.js.gz +0 -0
  203. package/modules/admin/dist/static/js/451.645974a8.js +0 -1
  204. package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
  205. package/modules/admin/dist/static/js/460.962d5bc0.js +0 -1
  206. package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
  207. package/modules/admin/dist/static/js/550.f27feb23.js +0 -1
  208. package/modules/admin/dist/static/js/550.f27feb23.js.gz +0 -0
  209. package/modules/admin/dist/static/js/556.1e08866a.js +0 -1
  210. package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
  211. package/modules/admin/dist/static/js/569.0fecfbee.js +0 -1
  212. package/modules/admin/dist/static/js/569.0fecfbee.js.gz +0 -0
  213. package/modules/admin/dist/static/js/572.13392e1d.js +0 -1
  214. package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
  215. package/modules/admin/dist/static/js/603.7b34a650.js +0 -1
  216. package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
  217. package/modules/admin/dist/static/js/651.564b24b6.js +0 -1
  218. package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
  219. package/modules/admin/dist/static/js/653.02ec1098.js +0 -1
  220. package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
  221. package/modules/admin/dist/static/js/750.50c950da.js +0 -1
  222. package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
  223. package/modules/admin/dist/static/js/950.d4ff0a18.js +0 -1
  224. package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
  225. package/modules/admin/dist/static/js/app.ea86ae11.js +0 -2
  226. package/modules/admin/dist/static/js/app.ea86ae11.js.LICENSE.txt.gz +0 -0
  227. package/modules/admin/dist/static/js/app.ea86ae11.js.gz +0 -0
  228. /package/modules/admin/dist/css/{651.e946bda7.css → 220.e946bda7.css} +0 -0
  229. /package/modules/admin/dist/css/{950.1fd9d57c.css → 338.1fd9d57c.css} +0 -0
  230. /package/modules/admin/dist/css/{750.4086915d.css → 913.4086915d.css} +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.20",
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.2.6",
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": "^15.3.0",
33
- "eslint": "^7.1.0",
34
- "mocha": "^11.7.2",
35
- "mocha-junit-reporter": "^2.0.2",
36
- "nodemon": "^3.1.10",
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.22",
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.2.6",
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": "^15.3.0",
33
+ "eslint": "^7.1.0",
34
+ "mocha": "^11.7.2",
35
+ "mocha-junit-reporter": "^2.0.2",
36
+ "nodemon": "^3.1.10",
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,36 +1,36 @@
1
- set -e
2
-
3
- rm -rf testdata
4
-
5
- node test/testserver.js &
6
- pid=$!
7
-
8
- cleanup() {
9
- if kill -0 "$pid" >/dev/null 2>&1; then
10
- kill "$pid" || true
11
- # give it a moment to exit gracefully
12
- sleep 1 || true
13
- if kill -0 "$pid" >/dev/null 2>&1; then
14
- kill -9 "$pid" || true
15
- fi
16
- fi
17
- }
18
- trap cleanup EXIT
19
-
20
- # Wait for server readiness
21
- attempts=0
22
- until curl -sSf "http://localhost:3001/admin" >/dev/null 2>&1; do
23
- attempts=$((attempts+1))
24
- if [ "$attempts" -gt 120 ]; then
25
- echo "Server did not become ready on http://localhost:3001/admin" >&2
26
- exit 1
27
- fi
28
- # bail out early if server died
29
- if ! kill -0 "$pid" >/dev/null 2>&1; then
30
- echo "Server process exited prematurely" >&2
31
- exit 1
32
- fi
33
- sleep 0.5
34
- done
35
-
1
+ set -e
2
+
3
+ rm -rf testdata
4
+
5
+ node test/testserver.js &
6
+ pid=$!
7
+
8
+ cleanup() {
9
+ if kill -0 "$pid" >/dev/null 2>&1; then
10
+ kill "$pid" || true
11
+ # give it a moment to exit gracefully
12
+ sleep 1 || true
13
+ if kill -0 "$pid" >/dev/null 2>&1; then
14
+ kill -9 "$pid" || true
15
+ fi
16
+ fi
17
+ }
18
+ trap cleanup EXIT
19
+
20
+ # Wait for server readiness
21
+ attempts=0
22
+ until curl -sSf "http://localhost:3001/admin" >/dev/null 2>&1; do
23
+ attempts=$((attempts+1))
24
+ if [ "$attempts" -gt 120 ]; then
25
+ echo "Server did not become ready on http://localhost:3001/admin" >&2
26
+ exit 1
27
+ fi
28
+ # bail out early if server died
29
+ if ! kill -0 "$pid" >/dev/null 2>&1; then
30
+ echo "Server process exited prematurely" >&2
31
+ exit 1
32
+ fi
33
+ sleep 0.5
34
+ done
35
+
36
36
  ./node_modules/.bin/cypress run
@@ -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:wkDPvFPkFtlJY55n@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
+ })