@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.
Files changed (33) hide show
  1. package/dist/src/MasterContainer.d.ts +18 -3
  2. package/dist/src/MasterContainer.d.ts.map +1 -1
  3. package/dist/src/MasterContainer.js +19 -1
  4. package/dist/src/MasterContainer.js.map +1 -1
  5. package/dist/src/bootstrap/Initializer.d.ts.map +1 -1
  6. package/dist/src/bootstrap/Initializer.js +0 -2
  7. package/dist/src/bootstrap/Initializer.js.map +1 -1
  8. package/dist/src/project/ProjectContainer.js +1 -1
  9. package/dist/src/project/ProjectContainer.js.map +1 -1
  10. package/dist/src/projectGroup/ProjectGroupContainer.js +1 -1
  11. package/dist/src/projectGroup/ProjectGroupContainer.js.map +1 -1
  12. package/dist/src/tsconfig.tsbuildinfo +1 -1
  13. package/dist/src/utils/sentry.d.ts +1 -1
  14. package/dist/src/utils/sentry.d.ts.map +1 -1
  15. package/dist/src/utils/sentry.js +1 -1
  16. package/dist/src/utils/sentry.js.map +1 -1
  17. package/dist/tests/e2e/assume-identity.test.d.ts +2 -0
  18. package/dist/tests/e2e/assume-identity.test.d.ts.map +1 -0
  19. package/dist/tests/e2e/assume-identity.test.js +109 -0
  20. package/dist/tests/e2e/assume-identity.test.js.map +1 -0
  21. package/dist/tests/src/requests.d.ts +2 -2
  22. package/dist/tests/src/requests.d.ts.map +1 -1
  23. package/dist/tests/src/requests.js +10 -1
  24. package/dist/tests/src/requests.js.map +1 -1
  25. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +23 -23
  27. package/src/MasterContainer.ts +38 -2
  28. package/src/bootstrap/Initializer.ts +0 -2
  29. package/src/project/ProjectContainer.ts +1 -1
  30. package/src/projectGroup/ProjectGroupContainer.ts +1 -1
  31. package/src/utils/sentry.ts +1 -1
  32. package/tests/e2e/assume-identity.test.ts +127 -0
  33. package/tests/src/requests.ts +12 -3
@@ -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 { ProjectGroupContainer, ProjectGroupResolver as ProjectGroupResolverInterface } from '@contember/engine-http'
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('koaMiddlewares', ({ contentApiMiddlewareFactory, tenantApiMiddlewareFactory, systemApiMiddlewareFactory, httpErrorMiddlewareFactory, debugMode, version, serverConfig }) =>
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, { timing: true }))
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', () =>
@@ -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(Sentry.Severity.Error)
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
+ })
@@ -1,6 +1,6 @@
1
1
  import { executeGraphql, gql, loginToken } from './tester'
2
2
  import { assert } from 'vitest'
3
- import { Membership } from '@contember/engine-tenant-api'
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
  }