@contember/engine-server 1.2.0-alpha.2 → 1.2.0-alpha.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/dist/src/MasterContainer.d.ts +18 -3
- package/dist/src/MasterContainer.d.ts.map +1 -1
- package/dist/src/MasterContainer.js +19 -1
- package/dist/src/MasterContainer.js.map +1 -1
- package/dist/src/bootstrap/Initializer.d.ts.map +1 -1
- package/dist/src/bootstrap/Initializer.js +0 -2
- package/dist/src/bootstrap/Initializer.js.map +1 -1
- package/dist/src/project/ProjectContainer.js +1 -1
- package/dist/src/project/ProjectContainer.js.map +1 -1
- package/dist/src/projectGroup/ProjectGroupContainer.js +1 -1
- package/dist/src/projectGroup/ProjectGroupContainer.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/utils/sentry.d.ts +1 -1
- package/dist/src/utils/sentry.d.ts.map +1 -1
- package/dist/src/utils/sentry.js +1 -1
- package/dist/src/utils/sentry.js.map +1 -1
- package/dist/tests/e2e/assume-identity.test.d.ts +2 -0
- package/dist/tests/e2e/assume-identity.test.d.ts.map +1 -0
- package/dist/tests/e2e/assume-identity.test.js +109 -0
- package/dist/tests/e2e/assume-identity.test.js.map +1 -0
- package/dist/tests/src/requests.d.ts +2 -2
- package/dist/tests/src/requests.d.ts.map +1 -1
- package/dist/tests/src/requests.js +10 -1
- package/dist/tests/src/requests.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -23
- package/src/MasterContainer.ts +38 -2
- package/src/bootstrap/Initializer.ts +0 -2
- package/src/project/ProjectContainer.ts +1 -1
- package/src/projectGroup/ProjectGroupContainer.ts +1 -1
- package/src/utils/sentry.ts +1 -1
- package/tests/e2e/assume-identity.test.ts +127 -0
- package/tests/src/requests.ts +12 -3
package/src/MasterContainer.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ContentApiMiddlewareFactory,
|
|
12
12
|
ContentGraphQLContextFactory,
|
|
13
13
|
ContentQueryHandlerFactory,
|
|
14
|
+
ContentSchemaTransferMappingFactory,
|
|
14
15
|
createHomepageMiddleware,
|
|
15
16
|
createModuleInfoMiddleware,
|
|
16
17
|
createPlaygroundMiddleware,
|
|
@@ -18,6 +19,10 @@ import {
|
|
|
18
19
|
createProviders,
|
|
19
20
|
createTimerMiddleware,
|
|
20
21
|
ErrorMiddlewareFactory,
|
|
22
|
+
ExportApiMiddlewareFactory,
|
|
23
|
+
ExportExecutor,
|
|
24
|
+
ImportApiMiddlewareFactory,
|
|
25
|
+
ImportExecutor,
|
|
21
26
|
Koa,
|
|
22
27
|
NotModifiedChecker,
|
|
23
28
|
Providers,
|
|
@@ -25,6 +30,7 @@ import {
|
|
|
25
30
|
SystemApiMiddlewareFactory,
|
|
26
31
|
SystemGraphQLContextFactory,
|
|
27
32
|
SystemGraphQLHandlerFactory,
|
|
33
|
+
SystemSchemaTransferMappingFactory,
|
|
28
34
|
TenantApiMiddlewareFactory,
|
|
29
35
|
TenantGraphQLContextFactory,
|
|
30
36
|
TenantGraphQLHandlerFactory,
|
|
@@ -37,7 +43,8 @@ import { TenantConfigResolver } from './config/tenantConfigResolver'
|
|
|
37
43
|
import { ProjectGroupContainerFactory } from './projectGroup/ProjectGroupContainer'
|
|
38
44
|
import corsMiddleware from '@koa/cors'
|
|
39
45
|
import { ProjectGroupResolver } from './projectGroup/ProjectGroupResolver'
|
|
40
|
-
import {
|
|
46
|
+
import { ProjectGroupResolver as ProjectGroupResolverInterface } from '@contember/engine-http'
|
|
47
|
+
import { Logger } from '@contember/engine-common'
|
|
41
48
|
|
|
42
49
|
export interface MasterContainer {
|
|
43
50
|
initializer: Initializer
|
|
@@ -114,7 +121,22 @@ export class MasterContainerFactory {
|
|
|
114
121
|
new SystemGraphQLContextFactory())
|
|
115
122
|
.addService('systemApiMiddlewareFactory', ({ debugMode, projectGroupResolver, systemGraphQLContextFactory }) =>
|
|
116
123
|
new SystemApiMiddlewareFactory(debugMode, projectGroupResolver, systemGraphQLContextFactory))
|
|
117
|
-
.addService('
|
|
124
|
+
.addService('logger', () =>
|
|
125
|
+
// eslint-disable-next-line no-console
|
|
126
|
+
new Logger(console.log))
|
|
127
|
+
.addService('contentSchemaTransferMappingFactory', () =>
|
|
128
|
+
new ContentSchemaTransferMappingFactory())
|
|
129
|
+
.addService('systemSchemaTransferMappingFactory', () =>
|
|
130
|
+
new SystemSchemaTransferMappingFactory())
|
|
131
|
+
.addService('importExecutor', ({ contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory, logger }) =>
|
|
132
|
+
new ImportExecutor(contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory, logger))
|
|
133
|
+
.addService('exportExecutor', ({ contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory }) =>
|
|
134
|
+
new ExportExecutor(contentSchemaTransferMappingFactory, systemSchemaTransferMappingFactory))
|
|
135
|
+
.addService('importApiMiddlewareFactory', ({ projectGroupResolver, importExecutor }) =>
|
|
136
|
+
new ImportApiMiddlewareFactory(projectGroupResolver, importExecutor))
|
|
137
|
+
.addService('exportApiMiddlewareFactory', ({ projectGroupResolver, exportExecutor }) =>
|
|
138
|
+
new ExportApiMiddlewareFactory(projectGroupResolver, exportExecutor))
|
|
139
|
+
.addService('koaMiddlewares', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, importApiMiddlewareFactory, exportApiMiddlewareFactory, httpErrorMiddlewareFactory, debugMode, version, serverConfig }) =>
|
|
118
140
|
compose([
|
|
119
141
|
koaCompress({
|
|
120
142
|
br: false,
|
|
@@ -149,6 +171,20 @@ export class MasterContainerFactory {
|
|
|
149
171
|
systemApiMiddlewareFactory.create(),
|
|
150
172
|
]),
|
|
151
173
|
),
|
|
174
|
+
route(
|
|
175
|
+
'/import$',
|
|
176
|
+
compose([
|
|
177
|
+
createModuleInfoMiddleware('transfer'),
|
|
178
|
+
importApiMiddlewareFactory.create(),
|
|
179
|
+
]),
|
|
180
|
+
),
|
|
181
|
+
route(
|
|
182
|
+
'/export$',
|
|
183
|
+
compose([
|
|
184
|
+
createModuleInfoMiddleware('transfer'),
|
|
185
|
+
exportApiMiddlewareFactory.create(),
|
|
186
|
+
]),
|
|
187
|
+
),
|
|
152
188
|
]))
|
|
153
189
|
.addService('koa', ({ koaMiddlewares }) => {
|
|
154
190
|
const app = new Koa()
|
|
@@ -17,7 +17,6 @@ export class Initializer {
|
|
|
17
17
|
await tenantContainer.migrationsRunner.run(logger.write.bind(logger))
|
|
18
18
|
logger.groupEnd()
|
|
19
19
|
|
|
20
|
-
const systemContainer = groupContainer.systemContainer
|
|
21
20
|
const projects: string[] = []
|
|
22
21
|
|
|
23
22
|
const tenantProjects = await tenantContainer.projectManager.getProjects(tenantContainer.databaseContext)
|
|
@@ -32,7 +31,6 @@ export class Initializer {
|
|
|
32
31
|
}
|
|
33
32
|
const project = projectContainer.project
|
|
34
33
|
projects.push(project.slug)
|
|
35
|
-
await systemContainer.projectInitializer.initialize(projectContainer.systemDatabaseContextFactory, project, logger)
|
|
36
34
|
logger.groupEnd()
|
|
37
35
|
}
|
|
38
36
|
// eslint-disable-next-line no-console
|
|
@@ -57,7 +57,7 @@ export class ProjectContainerFactory {
|
|
|
57
57
|
.addService('project', () =>
|
|
58
58
|
project)
|
|
59
59
|
.addService('connection', ({ project }) =>
|
|
60
|
-
Connection.create(project.db
|
|
60
|
+
Connection.create(project.db))
|
|
61
61
|
.addService('graphQlSchemaBuilderFactory', () =>
|
|
62
62
|
new GraphQlSchemaBuilderFactory())
|
|
63
63
|
.addService('permissionsByIdentityFactory', ({}) =>
|
|
@@ -51,7 +51,7 @@ export class ProjectGroupContainerFactory {
|
|
|
51
51
|
.addService('tenantDbCredentials', () =>
|
|
52
52
|
config.db)
|
|
53
53
|
.addService('tenantConnection', ({ tenantDbCredentials }): Connection.ConnectionType =>
|
|
54
|
-
Connection.create(tenantDbCredentials
|
|
54
|
+
Connection.create(tenantDbCredentials))
|
|
55
55
|
.addService('projectSchemaResolver', () =>
|
|
56
56
|
new ProjectSchemaResolverProxy())
|
|
57
57
|
.addService('projectInitializer', () =>
|
package/src/utils/sentry.ts
CHANGED
|
@@ -28,7 +28,7 @@ export const logSentryError = (error: any, context: SentryErrorContext) => {
|
|
|
28
28
|
scope.setTag('project', context.project)
|
|
29
29
|
}
|
|
30
30
|
scope.setTag('module', context.module)
|
|
31
|
-
scope.setLevel(
|
|
31
|
+
scope.setLevel('error')
|
|
32
32
|
scope.setUser({
|
|
33
33
|
id: context.user,
|
|
34
34
|
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { test } from 'vitest'
|
|
2
|
+
import { createTester, gql } from '../src/tester'
|
|
3
|
+
import { addProjectMember, signIn, signUp } from '../src/requests'
|
|
4
|
+
import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
|
|
5
|
+
import { AllowAllPermissionFactory } from '@contember/schema-utils'
|
|
6
|
+
|
|
7
|
+
namespace TagModel {
|
|
8
|
+
export class Tag {
|
|
9
|
+
label = def.stringColumn()
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
test('Content API: assume identity', async () => {
|
|
15
|
+
const tester = await createTester(createSchema(TagModel, schema => {
|
|
16
|
+
return {
|
|
17
|
+
...schema,
|
|
18
|
+
acl: {
|
|
19
|
+
roles: {
|
|
20
|
+
test: {
|
|
21
|
+
entities: new AllowAllPermissionFactory().create(schema.model),
|
|
22
|
+
variables: {},
|
|
23
|
+
system: {
|
|
24
|
+
history: true,
|
|
25
|
+
assumeIdentity: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
}))
|
|
32
|
+
|
|
33
|
+
const email = `john+${Date.now()}@doe.com`
|
|
34
|
+
const identityId = await signUp(email)
|
|
35
|
+
const authKey = await signIn(email)
|
|
36
|
+
await addProjectMember(identityId, tester.projectSlug, { role: 'test', variables: [] })
|
|
37
|
+
|
|
38
|
+
const assumedIdentityId = '65e049e7-4b22-487a-a93b-528b3127d967'
|
|
39
|
+
await tester(
|
|
40
|
+
gql`
|
|
41
|
+
mutation {
|
|
42
|
+
createTag(data: {label: "foo bar"}) {
|
|
43
|
+
ok
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`,
|
|
47
|
+
{ authorizationToken: authKey },
|
|
48
|
+
)
|
|
49
|
+
.set('X-Contember-assume-identity', assumedIdentityId)
|
|
50
|
+
.expect(200)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
await tester(
|
|
54
|
+
gql`
|
|
55
|
+
query {
|
|
56
|
+
events {
|
|
57
|
+
tableName
|
|
58
|
+
identityId
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
`,
|
|
62
|
+
{ authorizationToken: authKey, path: `/system/${tester.projectSlug}` },
|
|
63
|
+
)
|
|
64
|
+
.expect({ data: { events: [{ tableName: 'tag', identityId: assumedIdentityId }] } })
|
|
65
|
+
.expect(200)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
test('Content API: assume identity is declined', async () => {
|
|
70
|
+
const tester = await createTester(createSchema(TagModel, schema => {
|
|
71
|
+
return {
|
|
72
|
+
...schema,
|
|
73
|
+
acl: {
|
|
74
|
+
roles: {
|
|
75
|
+
foo: {
|
|
76
|
+
entities: {},
|
|
77
|
+
variables: {},
|
|
78
|
+
system: {
|
|
79
|
+
assumeIdentity: true,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
test: {
|
|
83
|
+
entities: new AllowAllPermissionFactory().create(schema.model),
|
|
84
|
+
variables: {},
|
|
85
|
+
system: {
|
|
86
|
+
history: true,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}))
|
|
93
|
+
|
|
94
|
+
const email = `john+${Date.now()}@doe.com`
|
|
95
|
+
const identityId = await signUp(email)
|
|
96
|
+
const authKey = await signIn(email)
|
|
97
|
+
await addProjectMember(identityId, tester.projectSlug, { role: 'test', variables: [] })
|
|
98
|
+
|
|
99
|
+
const assumedIdentityId = '65e049e7-4b22-487a-a93b-528b3127d967'
|
|
100
|
+
await tester(
|
|
101
|
+
gql`
|
|
102
|
+
mutation {
|
|
103
|
+
createTag(data: {label: "foo bar"}) {
|
|
104
|
+
ok
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`,
|
|
108
|
+
{ authorizationToken: authKey },
|
|
109
|
+
)
|
|
110
|
+
.set('X-Contember-assume-identity', assumedIdentityId)
|
|
111
|
+
.expect(200)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
await tester(
|
|
115
|
+
gql`
|
|
116
|
+
query {
|
|
117
|
+
events {
|
|
118
|
+
tableName
|
|
119
|
+
identityId
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
`,
|
|
123
|
+
{ authorizationToken: authKey, path: `/system/${tester.projectSlug}` },
|
|
124
|
+
)
|
|
125
|
+
.expect({ data: { events: [{ tableName: 'tag', identityId }] } })
|
|
126
|
+
.expect(200)
|
|
127
|
+
})
|
package/tests/src/requests.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { executeGraphql, gql, loginToken } from './tester'
|
|
2
2
|
import { assert } from 'vitest'
|
|
3
|
-
import {
|
|
3
|
+
import { Acl } from '@contember/schema'
|
|
4
4
|
|
|
5
5
|
export const signIn = async (email: string, password = '123456'): Promise<string> => {
|
|
6
6
|
const response = await executeGraphql(
|
|
@@ -51,13 +51,22 @@ export const signUp = async (email: string, password = '123456') => {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
export const addProjectMember = async (identityId: string, projectSlug: string, membership: Membership = { role: 'admin', variables: [] }) => {
|
|
54
|
+
export const addProjectMember = async (identityId: string, projectSlug: string, membership: Acl.Membership = { role: 'admin', variables: [] }) => {
|
|
55
55
|
await executeGraphql(
|
|
56
56
|
'/tenant',
|
|
57
57
|
gql`
|
|
58
58
|
mutation ($identity: String!, $projectSlug: String!, $membership: MembershipInput!) {
|
|
59
59
|
addProjectMember(identityId: $identity, projectSlug: $projectSlug, memberships: [$membership]) {
|
|
60
60
|
ok
|
|
61
|
+
error {
|
|
62
|
+
code
|
|
63
|
+
developerMessage
|
|
64
|
+
membershipValidation {
|
|
65
|
+
code
|
|
66
|
+
role
|
|
67
|
+
variable
|
|
68
|
+
}
|
|
69
|
+
}
|
|
61
70
|
}
|
|
62
71
|
}
|
|
63
72
|
`,
|
|
@@ -67,6 +76,6 @@ export const addProjectMember = async (identityId: string, projectSlug: string,
|
|
|
67
76
|
)
|
|
68
77
|
.expect(200)
|
|
69
78
|
.expect(response => {
|
|
70
|
-
assert.deepStrictEqual(response.body.data, { addProjectMember: { ok: true } })
|
|
79
|
+
assert.deepStrictEqual(response.body.data, { addProjectMember: { ok: true, error: null } })
|
|
71
80
|
})
|
|
72
81
|
}
|