@teamplay/backend 0.2.3 → 0.2.5
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/features/accessControl.js +50 -0
- package/features/serverAggregate.js +2 -2
- package/features/validateSchema.js +10 -5
- package/index.js +4 -30
- package/package.json +7 -7
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import sharedbAccess, { registerOrmRules } from '@teamplay/sharedb-access'
|
|
2
|
+
import { isAccessControl } from '@teamplay/utils/accessControl'
|
|
3
|
+
|
|
4
|
+
export default function accessControl (
|
|
5
|
+
backend,
|
|
6
|
+
{ models = {}, dontUseOldDocs = true, ...options } = {}
|
|
7
|
+
) {
|
|
8
|
+
sharedbAccess(backend, { dontUseOldDocs, ...options })
|
|
9
|
+
|
|
10
|
+
for (const modelPattern in models) {
|
|
11
|
+
const { access, factory } = models[modelPattern]
|
|
12
|
+
|
|
13
|
+
if (factory) {
|
|
14
|
+
// TODO: implement checking access from factory
|
|
15
|
+
throw Error('accessControl factory model: NOT IMPLEMENTED')
|
|
16
|
+
} else if (access) {
|
|
17
|
+
const collectionName = modelPattern
|
|
18
|
+
if (/\./.test(collectionName)) throw Error(ERRORS.onlyTopLevelCollections(modelPattern))
|
|
19
|
+
if (!isAccessControl(access)) throw Error(ERRORS.improperAccessControlProps(collectionName, access))
|
|
20
|
+
registerOrmRules(backend, collectionName, access)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log('✓ Security: Access Control for DB collections on backend is enabled')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ERRORS = {
|
|
28
|
+
onlyTopLevelCollections: (modelPattern) => `
|
|
29
|
+
accessControl: you can only define 'access' for access control rules in the top-level collection models
|
|
30
|
+
(i.e. 'model/items.js')
|
|
31
|
+
Found 'access' in '${modelPattern}'.
|
|
32
|
+
Move it to the top-level collection model: 'models/${modelPattern.split('.')[0]}.js'
|
|
33
|
+
`,
|
|
34
|
+
improperAccessControlProps: (collectionName, props) => `
|
|
35
|
+
accessControl: received incorrect 'access' object for accessControl.
|
|
36
|
+
Possibly not wrapped into an \`accessControl()\` call.
|
|
37
|
+
|
|
38
|
+
Make sure you wrap your 'access' object into an \`accessControl({})\` call:
|
|
39
|
+
Example:
|
|
40
|
+
import { accessControl } from 'startupjs'
|
|
41
|
+
export const access = accessControl({
|
|
42
|
+
create: () => true,
|
|
43
|
+
...
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
Collection name: '${collectionName}'
|
|
47
|
+
Got:
|
|
48
|
+
${JSON.stringify(props)}
|
|
49
|
+
`
|
|
50
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import _serverAggregate from '@teamplay/server-aggregate'
|
|
2
2
|
import { isAggregationFunction } from '@teamplay/utils/aggregation'
|
|
3
3
|
|
|
4
|
-
export default function serverAggregate (backend, {
|
|
5
|
-
_serverAggregate(backend,
|
|
4
|
+
export default function serverAggregate (backend, { models = {}, ...options } = {}) {
|
|
5
|
+
_serverAggregate(backend, options)
|
|
6
6
|
|
|
7
7
|
for (const modelPattern in models) {
|
|
8
8
|
for (const aggregationName in models[modelPattern]) {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import sharedbSchema from '@teamplay/sharedb-schema'
|
|
2
2
|
import { transformSchema } from '@teamplay/schema'
|
|
3
3
|
|
|
4
|
-
export default function validateSchema (backend, { models = {} } = {}) {
|
|
5
|
-
|
|
4
|
+
export default function validateSchema (backend, { models = {}, ...options } = {}) {
|
|
5
|
+
options = {
|
|
6
|
+
schemas: {},
|
|
7
|
+
formats: {},
|
|
8
|
+
validators: {},
|
|
9
|
+
...options
|
|
10
|
+
}
|
|
6
11
|
|
|
7
12
|
for (const modelPattern in models) {
|
|
8
13
|
let { schema, factory } = models[modelPattern]
|
|
@@ -16,18 +21,18 @@ export default function validateSchema (backend, { models = {} } = {}) {
|
|
|
16
21
|
if (/\./.test(collectionName)) throw Error(ERRORS.onlyTopLevelCollections(modelPattern))
|
|
17
22
|
// transform schema from simplified format to full format
|
|
18
23
|
schema = transformSchema(schema, { collectionName })
|
|
19
|
-
|
|
24
|
+
options.schemas[collectionName] = schema
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
// allow any 'service' collection structure
|
|
23
28
|
// since 'service' collection is used in our startupjs libraries
|
|
24
29
|
// and we don't have a tool to collect scheme from all packages right now
|
|
25
|
-
|
|
30
|
+
options.schemas.service = transformSchema({
|
|
26
31
|
type: 'object', properties: {}, additionalProperties: true
|
|
27
32
|
})
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
sharedbSchema(backend,
|
|
35
|
+
sharedbSchema(backend, options)
|
|
31
36
|
console.log('✓ Security: JSON-schema validation of DB collections on backend is enabled')
|
|
32
37
|
}
|
|
33
38
|
|
package/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import ShareDbAccess, {
|
|
2
|
-
registerOrmRules
|
|
3
|
-
} from '@teamplay/sharedb-access'
|
|
4
1
|
import ShareDB from 'sharedb'
|
|
5
2
|
import shareDbHooks from 'sharedb-hooks'
|
|
6
3
|
import { pubsub } from './redis/index.js'
|
|
@@ -8,12 +5,12 @@ import { db } from './db/index.js'
|
|
|
8
5
|
import maybeFlushRedis from './redis/maybeFlushRedis.js'
|
|
9
6
|
import initValidateSchema from './features/validateSchema.js'
|
|
10
7
|
import initServerAggregate from './features/serverAggregate.js'
|
|
8
|
+
import initAccessControl from './features/accessControl.js'
|
|
11
9
|
|
|
12
10
|
export { redis, redlock, Redlock } from './redis/index.js'
|
|
13
11
|
export { db, mongo, mongoClient, createMongoIndex, sqlite } from './db/index.js'
|
|
14
12
|
|
|
15
13
|
const usersConnectionCounter = {}
|
|
16
|
-
global.__clients = {}
|
|
17
14
|
|
|
18
15
|
export default function createBackend ({
|
|
19
16
|
secure = false,
|
|
@@ -46,39 +43,16 @@ export default function createBackend ({
|
|
|
46
43
|
|
|
47
44
|
if (hooks) hooks(backend)
|
|
48
45
|
|
|
49
|
-
const ORM = global.STARTUP_JS_ORM || {}
|
|
50
|
-
|
|
51
|
-
// sharedb-access
|
|
52
46
|
if (accessControl) {
|
|
53
|
-
|
|
54
|
-
new ShareDbAccess(backend, { dontUseOldDocs: true })
|
|
55
|
-
|
|
56
|
-
for (const path in ORM) {
|
|
57
|
-
const ormEntity = ORM[path].OrmEntity
|
|
58
|
-
|
|
59
|
-
const { access } = ormEntity
|
|
60
|
-
const isFactory = !!ormEntity.factory
|
|
61
|
-
|
|
62
|
-
// TODO:
|
|
63
|
-
// - move registerOrmRulesFromFactory and registerOrmRules to this library
|
|
64
|
-
// - rewrite factories check to not use model anymore
|
|
65
|
-
if (isFactory) {
|
|
66
|
-
throw Error('Sharedb-access does not support ORM factories yet')
|
|
67
|
-
// registerOrmRulesFromFactory(backend, path, ormEntity)
|
|
68
|
-
} else if (access) {
|
|
69
|
-
registerOrmRules(backend, path, access)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
console.log('sharedb-access is working')
|
|
47
|
+
initAccessControl(backend, { models, ...(typeof accessControl === 'object' ? accessControl : {}) })
|
|
74
48
|
}
|
|
75
49
|
|
|
76
50
|
if (serverAggregate) {
|
|
77
|
-
initServerAggregate(backend, {
|
|
51
|
+
initServerAggregate(backend, { models, ...(typeof serverAggregate === 'object' ? serverAggregate : {}) })
|
|
78
52
|
}
|
|
79
53
|
|
|
80
54
|
if (validateSchema && process.env.NODE_ENV !== 'production') {
|
|
81
|
-
initValidateSchema(backend, { models })
|
|
55
|
+
initValidateSchema(backend, { models, ...(typeof validateSchema === 'object' ? validateSchema : {}) })
|
|
82
56
|
}
|
|
83
57
|
|
|
84
58
|
backend.on('client', (client, reject) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamplay/backend",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Create new ShareDB backend instance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
".": "./index.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@teamplay/schema": "^0.2.
|
|
16
|
-
"@teamplay/server-aggregate": "^0.2.
|
|
17
|
-
"@teamplay/sharedb-access": "^0.2.
|
|
18
|
-
"@teamplay/sharedb-schema": "^0.2.
|
|
19
|
-
"@teamplay/utils": "^0.2.
|
|
15
|
+
"@teamplay/schema": "^0.2.5",
|
|
16
|
+
"@teamplay/server-aggregate": "^0.2.5",
|
|
17
|
+
"@teamplay/sharedb-access": "^0.2.5",
|
|
18
|
+
"@teamplay/sharedb-schema": "^0.2.5",
|
|
19
|
+
"@teamplay/utils": "^0.2.5",
|
|
20
20
|
"@types/ioredis-mock": "^8.2.5",
|
|
21
21
|
"ioredis": "^5.3.2",
|
|
22
22
|
"ioredis-mock": "^8.9.0",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"sharedb-redis-pubsub": "^2.0.1",
|
|
30
30
|
"sqlite3": "^5.1.6"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "e4ea7de3c12214a24928af14b882651b3aeb5599"
|
|
33
33
|
}
|