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.
- package/.circleci/config.yml +21 -21
- package/.eslintrc.json +29 -29
- package/.vscode/launch.json +19 -0
- package/LICENSE +21 -21
- package/README.md +137 -137
- package/auth/index.js +76 -76
- package/auth/jwt.js +31 -31
- package/controllers/collections.js +260 -260
- package/controllers/install.js +105 -105
- package/controllers/status.js +43 -43
- package/controllers/users.js +52 -52
- package/cypress/fixtures/example.json +4 -4
- package/cypress/integration/0_install_spec.js +8 -8
- package/cypress/integration/custom_collections.js +30 -30
- package/cypress/integration/home.js +9 -9
- package/cypress/integration/settings.js +34 -34
- package/cypress/integration/users.js +61 -61
- package/cypress/plugins/index.js +17 -17
- package/cypress/support/commands.js +69 -69
- package/cypress/support/index.js +20 -20
- package/cypress/support/util.js +10 -10
- package/cypress.config.js +18 -18
- package/cypress.json +4 -4
- package/db/cached.js +44 -40
- package/db/file.js +131 -112
- package/db/memory.js +92 -79
- package/db/mongo.js +93 -86
- package/db/postgres.js +100 -93
- package/doc/authentication.md +38 -38
- package/doc/automatic-fields.md +12 -12
- package/doc/blogexample.md +16 -16
- package/doc/custom-endpoints.md +20 -20
- package/doc/database.md +23 -23
- package/doc/development.md +33 -33
- package/doc/listeners.md +103 -103
- package/doc/modules.md +8 -8
- package/doc/permissions.md +14 -14
- package/doc/relationships.md +65 -65
- package/doc/testing.md +47 -47
- package/doc/uploading-files.md +53 -53
- package/index.js +297 -297
- package/listeners.js +65 -65
- package/listeners_collection_permissions.js +29 -29
- package/listeners_users.js +96 -96
- package/listeners_validation.js +43 -43
- package/middleware/logging.js +30 -30
- package/middleware/permissions.js +41 -41
- package/modules/access_keys/access_keys.js +32 -32
- package/modules/admin/.babelrc +19 -19
- package/modules/admin/.editorconfig +14 -14
- package/modules/admin/.eslintignore +5 -5
- package/modules/admin/.eslintrc.js +197 -197
- package/modules/admin/.postcssrc.js +10 -10
- package/modules/admin/.travis.yml +5 -5
- package/modules/admin/LICENSE +21 -21
- package/modules/admin/README.md +88 -88
- package/modules/admin/build/build.js +46 -46
- package/modules/admin/build/check-versions.js +64 -64
- package/modules/admin/build/utils.js +109 -109
- package/modules/admin/build/vue-loader.conf.js +5 -5
- package/modules/admin/build/webpack.base.conf.js +112 -112
- package/modules/admin/build/webpack.dev.conf.js +95 -95
- package/modules/admin/build/webpack.prod.conf.js +112 -112
- package/modules/admin/config/dev.env.js +8 -8
- package/modules/admin/config/index.js +86 -86
- package/modules/admin/config/prod.env.js +5 -5
- package/modules/admin/dist/css/136.1055b646.css +69 -0
- package/modules/admin/dist/css/136.1055b646.css.gz +0 -0
- package/modules/admin/dist/css/{430.8c9b0482.css → 165.e83d8cfe.css} +4 -4
- package/modules/admin/dist/css/165.e83d8cfe.css.gz +0 -0
- package/modules/admin/dist/css/220.e946bda7.css.gz +0 -0
- package/modules/admin/dist/css/{197.7a90435e.css → 236.e66ce8d8.css} +4 -4
- package/modules/admin/dist/css/236.e66ce8d8.css.gz +0 -0
- package/modules/admin/dist/css/338.1fd9d57c.css.gz +0 -0
- package/modules/admin/dist/css/{566.7a90435e.css → 566.e66ce8d8.css} +4 -4
- package/modules/admin/dist/css/566.e66ce8d8.css.gz +0 -0
- package/modules/admin/dist/css/76.46fe6799.css +66 -0
- package/modules/admin/dist/css/76.46fe6799.css.gz +0 -0
- package/modules/admin/dist/css/807.f450521e.css +1 -0
- package/modules/admin/dist/css/807.f450521e.css.gz +0 -0
- package/modules/admin/dist/css/{750.4086915d.css.gz → 913.4086915d.css.gz} +0 -0
- package/modules/admin/dist/css/{app.eba5f5e2.css → app.1c3232a3.css} +25 -25
- package/modules/admin/dist/css/app.1c3232a3.css.gz +0 -0
- package/modules/admin/dist/index.html +1 -1
- package/modules/admin/dist/static/js/115.108d0dd5.js +1 -0
- package/modules/admin/dist/static/js/115.108d0dd5.js.gz +0 -0
- package/modules/admin/dist/static/js/136.1f9f4cb0.js +1 -0
- package/modules/admin/dist/static/js/136.1f9f4cb0.js.gz +0 -0
- package/modules/admin/dist/static/js/165.b3d51941.js +1 -0
- package/modules/admin/dist/static/js/165.b3d51941.js.gz +0 -0
- package/modules/admin/dist/static/js/220.02b2cd49.js +1 -0
- package/modules/admin/dist/static/js/220.02b2cd49.js.gz +0 -0
- package/modules/admin/dist/static/js/236.98c79868.js +1 -0
- package/modules/admin/dist/static/js/236.98c79868.js.gz +0 -0
- package/modules/admin/dist/static/js/338.4ba49501.js +1 -0
- package/modules/admin/dist/static/js/338.4ba49501.js.gz +0 -0
- package/modules/admin/dist/static/js/381.a05421de.js +1 -0
- package/modules/admin/dist/static/js/381.a05421de.js.gz +0 -0
- package/modules/admin/dist/static/js/412.0914ff23.js +1 -0
- package/modules/admin/dist/static/js/412.0914ff23.js.gz +0 -0
- package/modules/admin/dist/static/js/533.507df4cb.js +1 -0
- package/modules/admin/dist/static/js/533.507df4cb.js.gz +0 -0
- package/modules/admin/dist/static/js/556.d7586b89.js +1 -0
- package/modules/admin/dist/static/js/556.d7586b89.js.gz +0 -0
- package/modules/admin/dist/static/js/76.811d0e96.js +1 -0
- package/modules/admin/dist/static/js/76.811d0e96.js.gz +0 -0
- package/modules/admin/dist/static/js/807.8b7455a7.js +1 -0
- package/modules/admin/dist/static/js/807.8b7455a7.js.gz +0 -0
- package/modules/admin/dist/static/js/913.8b376386.js +1 -0
- package/modules/admin/dist/static/js/913.8b376386.js.gz +0 -0
- package/modules/admin/dist/static/js/app.834abee4.js +2 -0
- package/modules/admin/dist/static/js/{app.ea86ae11.js.LICENSE.txt → app.834abee4.js.LICENSE.txt} +3 -3
- package/modules/admin/dist/static/js/app.834abee4.js.LICENSE.txt.gz +0 -0
- package/modules/admin/dist/static/js/app.834abee4.js.gz +0 -0
- package/modules/admin/index.html +16 -16
- package/modules/admin/package.json +102 -101
- package/modules/admin/src/App.vue +11 -11
- package/modules/admin/src/api/login.js +26 -26
- package/modules/admin/src/api/table.js +9 -9
- package/modules/admin/src/components/Breadcrumb/index.vue +79 -79
- package/modules/admin/src/components/Hamburger/index.vue +62 -62
- package/modules/admin/src/components/JSONEditor.vue +206 -180
- package/modules/admin/src/components/SvgIcon/index.vue +43 -43
- package/modules/admin/src/icons/index.js +9 -9
- package/modules/admin/src/icons/svgo.yml +22 -22
- package/modules/admin/src/main.js +42 -42
- package/modules/admin/src/permission.js +49 -49
- package/modules/admin/src/router/index.js +200 -200
- package/modules/admin/src/store/getters.js +11 -11
- package/modules/admin/src/store/index.js +17 -17
- package/modules/admin/src/store/modules/app.js +43 -43
- package/modules/admin/src/store/modules/user.js +104 -104
- package/modules/admin/src/styles/element-ui.scss +29 -29
- package/modules/admin/src/styles/index.scss +78 -78
- package/modules/admin/src/styles/mixin.scss +27 -27
- package/modules/admin/src/styles/sidebar.scss +133 -133
- package/modules/admin/src/styles/transition.scss +46 -46
- package/modules/admin/src/styles/variables.scss +4 -4
- package/modules/admin/src/utils/auth.js +15 -15
- package/modules/admin/src/utils/index.js +74 -74
- package/modules/admin/src/utils/request.js +47 -48
- package/modules/admin/src/utils/validate.js +31 -31
- package/modules/admin/src/views/404.vue +235 -235
- package/modules/admin/src/views/Dev.vue +33 -33
- package/modules/admin/src/views/EditDocument.vue +121 -121
- package/modules/admin/src/views/Endpoints.vue +279 -279
- package/modules/admin/src/views/Home.vue +84 -84
- package/modules/admin/src/views/Install.vue +79 -79
- package/modules/admin/src/views/ListDocuments.vue +72 -72
- package/modules/admin/src/views/ListDocuments2.vue +467 -467
- package/modules/admin/src/views/ManageListeners.vue +67 -67
- package/modules/admin/src/views/ManageMiddleware.vue +43 -43
- package/modules/admin/src/views/ManagePermissions.vue +75 -75
- package/modules/admin/src/views/ViewRequest.vue +77 -77
- package/modules/admin/src/views/form/index.vue +91 -91
- package/modules/admin/src/views/layout/Layout.vue +69 -69
- package/modules/admin/src/views/layout/components/AppMain.vue +41 -41
- package/modules/admin/src/views/layout/components/Navbar.vue +97 -97
- package/modules/admin/src/views/layout/components/Sidebar/Item.vue +29 -29
- package/modules/admin/src/views/layout/components/Sidebar/Link.vue +39 -39
- package/modules/admin/src/views/layout/components/Sidebar/SidebarItem.vue +103 -103
- package/modules/admin/src/views/layout/components/Sidebar/index.vue +62 -62
- package/modules/admin/src/views/layout/components/index.js +3 -3
- package/modules/admin/src/views/layout/mixin/ResizeHandler.js +41 -41
- package/modules/admin/src/views/login/index.vue +195 -195
- package/modules/admin/src/views/tree/index.vue +77 -77
- package/modules/collections/collections.js +39 -39
- package/modules/core/core.js +197 -197
- package/modules/logging/logging.js +88 -88
- package/modules/permissions/permissions.js +106 -106
- package/package.json +59 -59
- package/scripts/expressa +12 -12
- package/scripts/run_cypress_tests.sh +35 -35
- package/scripts/run_db_tests.sh +8 -8
- package/test/0-install.js +96 -96
- package/test/collections.js +431 -431
- package/test/collections.querying.js +288 -288
- package/test/db.js +258 -258
- package/test/db.strings.js +73 -73
- package/test/db.updating.js +186 -144
- package/test/logging.js +29 -29
- package/test/test.js +93 -93
- package/test/testserver.js +30 -17
- package/test/testutils.js +136 -136
- package/test/users.js +425 -425
- package/util.js +522 -522
- package/modules/admin/dist/css/197.7a90435e.css.gz +0 -0
- package/modules/admin/dist/css/430.8c9b0482.css.gz +0 -0
- package/modules/admin/dist/css/451.c6646d20.css +0 -1
- package/modules/admin/dist/css/451.c6646d20.css.gz +0 -0
- package/modules/admin/dist/css/566.7a90435e.css.gz +0 -0
- package/modules/admin/dist/css/569.f7d5c7d5.css +0 -37
- package/modules/admin/dist/css/569.f7d5c7d5.css.gz +0 -0
- package/modules/admin/dist/css/572.74d8e965.css +0 -34
- package/modules/admin/dist/css/572.74d8e965.css.gz +0 -0
- package/modules/admin/dist/css/651.e946bda7.css.gz +0 -0
- package/modules/admin/dist/css/950.1fd9d57c.css.gz +0 -0
- package/modules/admin/dist/css/app.eba5f5e2.css.gz +0 -0
- package/modules/admin/dist/static/js/197.e511d91e.js +0 -1
- package/modules/admin/dist/static/js/197.e511d91e.js.gz +0 -0
- package/modules/admin/dist/static/js/430.b3941f30.js +0 -1
- package/modules/admin/dist/static/js/430.b3941f30.js.gz +0 -0
- package/modules/admin/dist/static/js/451.645974a8.js +0 -1
- package/modules/admin/dist/static/js/451.645974a8.js.gz +0 -0
- package/modules/admin/dist/static/js/460.962d5bc0.js +0 -1
- package/modules/admin/dist/static/js/460.962d5bc0.js.gz +0 -0
- package/modules/admin/dist/static/js/550.f27feb23.js +0 -1
- package/modules/admin/dist/static/js/550.f27feb23.js.gz +0 -0
- package/modules/admin/dist/static/js/556.1e08866a.js +0 -1
- package/modules/admin/dist/static/js/556.1e08866a.js.gz +0 -0
- package/modules/admin/dist/static/js/569.0fecfbee.js +0 -1
- package/modules/admin/dist/static/js/569.0fecfbee.js.gz +0 -0
- package/modules/admin/dist/static/js/572.13392e1d.js +0 -1
- package/modules/admin/dist/static/js/572.13392e1d.js.gz +0 -0
- package/modules/admin/dist/static/js/603.7b34a650.js +0 -1
- package/modules/admin/dist/static/js/603.7b34a650.js.gz +0 -0
- package/modules/admin/dist/static/js/651.564b24b6.js +0 -1
- package/modules/admin/dist/static/js/651.564b24b6.js.gz +0 -0
- package/modules/admin/dist/static/js/653.02ec1098.js +0 -1
- package/modules/admin/dist/static/js/653.02ec1098.js.gz +0 -0
- package/modules/admin/dist/static/js/750.50c950da.js +0 -1
- package/modules/admin/dist/static/js/750.50c950da.js.gz +0 -0
- package/modules/admin/dist/static/js/950.d4ff0a18.js +0 -1
- package/modules/admin/dist/static/js/950.d4ff0a18.js.gz +0 -0
- package/modules/admin/dist/static/js/app.ea86ae11.js +0 -2
- package/modules/admin/dist/static/js/app.ea86ae11.js.LICENSE.txt.gz +0 -0
- package/modules/admin/dist/static/js/app.ea86ae11.js.gz +0 -0
- /package/modules/admin/dist/css/{651.e946bda7.css → 220.e946bda7.css} +0 -0
- /package/modules/admin/dist/css/{950.1fd9d57c.css → 338.1fd9d57c.css} +0 -0
- /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.
|
|
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
|
package/scripts/run_db_tests.sh
CHANGED
|
@@ -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:
|
|
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
|
+
})
|