@contember/engine-server 1.2.0-alpha.1 → 1.2.0-alpha.10

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 (79) 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 +20 -2
  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/acl-condition-variable.test.d.ts +2 -0
  18. package/dist/tests/e2e/acl-condition-variable.test.d.ts.map +1 -0
  19. package/dist/tests/e2e/acl-condition-variable.test.js +77 -0
  20. package/dist/tests/e2e/acl-condition-variable.test.js.map +1 -0
  21. package/dist/tests/e2e/assume-identity.test.d.ts +2 -0
  22. package/dist/tests/e2e/assume-identity.test.d.ts.map +1 -0
  23. package/dist/tests/e2e/assume-identity.test.js +109 -0
  24. package/dist/tests/e2e/assume-identity.test.js.map +1 -0
  25. package/dist/tests/e2e/assume-membership.test.d.ts +2 -0
  26. package/dist/tests/e2e/assume-membership.test.d.ts.map +1 -0
  27. package/dist/tests/e2e/assume-membership.test.js +58 -0
  28. package/dist/tests/e2e/assume-membership.test.js.map +1 -0
  29. package/dist/tests/e2e/content-api-basic.test.d.ts +2 -0
  30. package/dist/tests/e2e/content-api-basic.test.d.ts.map +1 -0
  31. package/dist/tests/e2e/content-api-basic.test.js +50 -0
  32. package/dist/tests/e2e/content-api-basic.test.js.map +1 -0
  33. package/dist/tests/e2e/content-invalid-schema.test.d.ts +2 -0
  34. package/dist/tests/e2e/content-invalid-schema.test.d.ts.map +1 -0
  35. package/dist/tests/e2e/content-invalid-schema.test.js +29 -0
  36. package/dist/tests/e2e/content-invalid-schema.test.js.map +1 -0
  37. package/dist/tests/e2e/homepage.test.d.ts +2 -0
  38. package/dist/tests/e2e/homepage.test.d.ts.map +1 -0
  39. package/dist/tests/e2e/homepage.test.js +15 -0
  40. package/dist/tests/e2e/homepage.test.js.map +1 -0
  41. package/dist/tests/e2e/tenant-member-access.test.d.ts +2 -0
  42. package/dist/tests/e2e/tenant-member-access.test.d.ts.map +1 -0
  43. package/dist/tests/e2e/tenant-member-access.test.js +43 -0
  44. package/dist/tests/e2e/tenant-member-access.test.js.map +1 -0
  45. package/dist/tests/e2e/x-contember-ref.test.d.ts +2 -0
  46. package/dist/tests/e2e/x-contember-ref.test.d.ts.map +1 -0
  47. package/dist/tests/e2e/x-contember-ref.test.js +63 -0
  48. package/dist/tests/e2e/x-contember-ref.test.js.map +1 -0
  49. package/dist/tests/{e2e → src}/requests.d.ts +2 -1
  50. package/dist/tests/src/requests.d.ts.map +1 -0
  51. package/dist/tests/{e2e → src}/requests.js +14 -5
  52. package/dist/tests/{e2e → src}/requests.js.map +1 -1
  53. package/dist/tests/{e2e → src}/tester.d.ts +0 -0
  54. package/dist/tests/{e2e → src}/tester.d.ts.map +1 -1
  55. package/dist/tests/{e2e → src}/tester.js +0 -0
  56. package/dist/tests/{e2e → src}/tester.js.map +1 -1
  57. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +23 -23
  59. package/src/MasterContainer.ts +39 -3
  60. package/src/bootstrap/Initializer.ts +0 -2
  61. package/src/project/ProjectContainer.ts +1 -1
  62. package/src/projectGroup/ProjectGroupContainer.ts +1 -1
  63. package/src/utils/sentry.ts +1 -1
  64. package/tests/e2e/acl-condition-variable.test.ts +74 -0
  65. package/tests/e2e/assume-identity.test.ts +127 -0
  66. package/tests/e2e/assume-membership.test.ts +64 -0
  67. package/tests/e2e/content-api-basic.test.ts +51 -0
  68. package/tests/e2e/content-invalid-schema.test.ts +31 -0
  69. package/tests/e2e/homepage.test.ts +10 -0
  70. package/tests/e2e/tenant-member-access.test.ts +51 -0
  71. package/tests/e2e/x-contember-ref.test.ts +71 -0
  72. package/tests/{e2e → src}/requests.ts +15 -5
  73. package/tests/{e2e → src}/tester.ts +0 -0
  74. package/dist/tests/e2e/http.test.d.ts +0 -2
  75. package/dist/tests/e2e/http.test.d.ts.map +0 -1
  76. package/dist/tests/e2e/http.test.js +0 -192
  77. package/dist/tests/e2e/http.test.js.map +0 -1
  78. package/dist/tests/e2e/requests.d.ts.map +0 -1
  79. package/tests/e2e/http.test.ts +0 -237
@@ -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,74 @@
1
+ import { assert, test } from 'vitest'
2
+ import { createTester, gql } from '../src/tester'
3
+ import { createSchema, SchemaDefinition as def, AclDefinition as acl } from '@contember/schema-definition'
4
+ import { addProjectMember, signIn, signUp } from '../src/requests'
5
+
6
+ namespace ArticleModel {
7
+ export const readerRole = acl.createRole('reader')
8
+ export const subscriptionVariable = acl.createConditionVariable('subscription', readerRole)
9
+
10
+ @acl.allow(readerRole, {
11
+ read: true,
12
+ when: {
13
+ publishedAt: subscriptionVariable,
14
+ },
15
+ })
16
+ export class Article {
17
+ publishedAt = def.dateTimeColumn().notNull()
18
+ }
19
+ }
20
+
21
+ test('ACL: condition variable', async () => {
22
+ const tester = await createTester(createSchema(ArticleModel))
23
+
24
+ await tester(
25
+ gql`
26
+ mutation {
27
+ articleA: createArticle(data: { publishedAt: "2022-02-01" }) {
28
+ ok
29
+ }
30
+ articleB: createArticle(data: { publishedAt: "2021-12-01" }) {
31
+ ok
32
+ }
33
+ }
34
+ `,
35
+ )
36
+ .expect(response => {
37
+ assert.deepStrictEqual(response.body.data, {
38
+ articleA: {
39
+ ok: true,
40
+ },
41
+ articleB: {
42
+ ok: true,
43
+ },
44
+ })
45
+ })
46
+ .expect(200)
47
+
48
+
49
+ const email = `john+${Date.now()}@doe.com`
50
+ const identityId = await signUp(email)
51
+ const authKey = await signIn(email)
52
+ await addProjectMember(identityId, tester.projectSlug, { role: 'reader', variables: [{ name: 'subscription', values: [JSON.stringify({ gte: '2022-01-01' })] }] })
53
+
54
+ await tester(
55
+ gql`
56
+ query {
57
+ listArticle {
58
+ publishedAt
59
+ }
60
+ }
61
+ `,
62
+ { authorizationToken: authKey },
63
+ )
64
+ .expect(response => {
65
+ assert.deepStrictEqual(response.body.data, {
66
+ listArticle: [
67
+ {
68
+ publishedAt: '2022-02-01T00:00:00.000Z',
69
+ },
70
+ ],
71
+ })
72
+ })
73
+ .expect(200)
74
+ })
@@ -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
+ })
@@ -0,0 +1,64 @@
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
+
6
+ namespace TagModel {
7
+ export class Tag {
8
+ label = def.stringColumn()
9
+ }
10
+ }
11
+
12
+
13
+ test('Content API: assume membership', async () => {
14
+ const tester = await createTester(createSchema(TagModel, schema => {
15
+ return {
16
+ ...schema,
17
+ acl: {
18
+ roles: {
19
+ test: {
20
+ entities: {},
21
+ variables: {},
22
+ content: {
23
+ assumeMembership: {
24
+ admin: {},
25
+ },
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
+ await tester(
39
+ gql`
40
+ query {
41
+ listTag {
42
+ id
43
+ }
44
+ }
45
+ `,
46
+ { authorizationToken: authKey },
47
+ )
48
+ .expect(400)
49
+
50
+
51
+ await tester(
52
+ gql`
53
+ query {
54
+ listTag {
55
+ id
56
+ }
57
+ }
58
+ `,
59
+ { authorizationToken: authKey },
60
+ )
61
+ .set('X-Contember-assume-membership', JSON.stringify({ memberships: [{ role: 'admin', variables: [] }] }))
62
+ .expect({ data: { listTag: [] } })
63
+ .expect(200)
64
+ })
@@ -0,0 +1,51 @@
1
+ import { assert, test } from 'vitest'
2
+ import { createTester, gql } from '../src/tester'
3
+ import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
4
+
5
+ namespace TagModel {
6
+ export class Tag {
7
+ label = def.stringColumn()
8
+ }
9
+ }
10
+
11
+ test('Content API: create & read tag', async () => {
12
+ const tester = await createTester(createSchema(TagModel))
13
+
14
+ await tester(
15
+ gql`
16
+ mutation {
17
+ createTag(data: { label: "graphql" }) {
18
+ ok
19
+ }
20
+ }
21
+ `,
22
+ )
23
+ .expect(response => {
24
+ assert.deepStrictEqual(response.body.data, {
25
+ createTag: {
26
+ ok: true,
27
+ },
28
+ })
29
+ })
30
+ .expect(200)
31
+
32
+ await tester(
33
+ gql`
34
+ query {
35
+ listTag(filter: { label: { eq: "graphql" } }) {
36
+ label
37
+ }
38
+ }
39
+ `,
40
+ )
41
+ .expect(response => {
42
+ assert.deepStrictEqual(response.body.data, {
43
+ listTag: [
44
+ {
45
+ label: 'graphql',
46
+ },
47
+ ],
48
+ })
49
+ })
50
+ .expect(200)
51
+ })
@@ -0,0 +1,31 @@
1
+ import { assert, test } from 'vitest'
2
+ import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
3
+ import { createTester, gql } from '../src/tester'
4
+
5
+
6
+ namespace TagModel {
7
+ export class Tag {
8
+ label = def.stringColumn()
9
+ }
10
+ }
11
+
12
+ test('Content API: invalid schema error', async () => {
13
+ const tester = await createTester(createSchema(TagModel))
14
+
15
+ await tester(
16
+ gql`
17
+ mutation {
18
+ createFoo(data: { label: "graphql" }) {
19
+ ok
20
+ }
21
+ }
22
+ `,
23
+ )
24
+ .expect(400)
25
+ .expect(response => {
26
+ assert.deepStrictEqual(
27
+ response.body.errors[0].message,
28
+ 'Cannot query field "createFoo" on type "Mutation". Did you mean "createTag"?',
29
+ )
30
+ })
31
+ })
@@ -0,0 +1,10 @@
1
+ import { test } from 'vitest'
2
+ import supertest from 'supertest'
3
+ import { apiUrl } from '../src/tester'
4
+
5
+ test('show homepage', async () => {
6
+ await supertest(apiUrl)
7
+ .get('/')
8
+ .expect(200)
9
+ .expect('App is running')
10
+ })
@@ -0,0 +1,51 @@
1
+ import { assert, test } from 'vitest'
2
+ import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
3
+ import { createTester, gql } from '../src/tester'
4
+ import { addProjectMember, signIn, signUp } from '../src/requests'
5
+
6
+
7
+ namespace TagModel {
8
+ export class Tag {
9
+ label = def.stringColumn()
10
+ }
11
+ }
12
+
13
+
14
+ test('Tenant API: sign up, add to a project and check project access', async () => {
15
+ const tester = await createTester(createSchema(TagModel))
16
+
17
+ const email = `john+${Date.now()}@doe.com`
18
+ const identityId = await signUp(email)
19
+ const authKey = await signIn(email)
20
+
21
+ await tester(
22
+ gql`
23
+ query {
24
+ listTag {
25
+ id
26
+ }
27
+ }
28
+ `,
29
+ { authorizationToken: authKey },
30
+ )
31
+ .expect(404)
32
+ .expect({ errors: [{ message: `Project ${tester.projectSlug} NOT found`, code: 404 }] })
33
+
34
+
35
+ await addProjectMember(identityId, tester.projectSlug)
36
+
37
+ await tester(
38
+ gql`
39
+ query {
40
+ listTag {
41
+ id
42
+ }
43
+ }
44
+ `,
45
+ { authorizationToken: authKey },
46
+ )
47
+ .expect(response => {
48
+ assert.deepStrictEqual(response.body.data, { listTag: [] })
49
+ })
50
+ .expect(200)
51
+ })
@@ -0,0 +1,71 @@
1
+ import { assert, test } from 'vitest'
2
+ import { createTester, gql } from '../src/tester'
3
+ import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
4
+
5
+ namespace TagModel {
6
+ export class Tag {
7
+ label = def.stringColumn()
8
+ }
9
+ }
10
+
11
+
12
+ test('Content API: X-Contember-Ref header', async () => {
13
+
14
+ const tester = await createTester(createSchema(TagModel))
15
+
16
+ await tester(
17
+ gql`
18
+ mutation {
19
+ createTag(data: { label: "typescript" }) {
20
+ ok
21
+ }
22
+ }
23
+ `,
24
+ ).expect(200)
25
+
26
+ const response = await tester(
27
+ gql`
28
+ query {
29
+ listTag(filter: { label: { eq: "typescript" } }) {
30
+ label
31
+ }
32
+ }
33
+ `,
34
+ )
35
+ .set('X-Contember-Ref', 'None')
36
+ .expect(response => {
37
+ assert.deepStrictEqual(response.body.data, {
38
+ listTag: [
39
+ {
40
+ label: 'typescript',
41
+ },
42
+ ],
43
+ })
44
+ })
45
+ .expect(200)
46
+ const eventKey = response.get('X-Contember-Ref')
47
+ await tester(
48
+ gql`
49
+ query {
50
+ listTag {
51
+ label
52
+ }
53
+ }
54
+ `,
55
+ )
56
+ .set('X-Contember-Ref', eventKey)
57
+ .expect(304)
58
+
59
+ // ignored for mutation
60
+ await tester(
61
+ gql`
62
+ mutation {
63
+ createTag(data: { label: "typescript" }) {
64
+ ok
65
+ }
66
+ }
67
+ `,
68
+ )
69
+ .set('X-Contember-Ref', eventKey)
70
+ .expect(200)
71
+ })
@@ -1,5 +1,6 @@
1
1
  import { executeGraphql, gql, loginToken } from './tester'
2
2
  import { assert } from 'vitest'
3
+ import { Acl } from '@contember/schema'
3
4
 
4
5
  export const signIn = async (email: string, password = '123456'): Promise<string> => {
5
6
  const response = await executeGraphql(
@@ -50,22 +51,31 @@ export const signUp = async (email: string, password = '123456') => {
50
51
  }
51
52
 
52
53
 
53
- export const addProjectMember = async (identityId: string, projectSlug: string, role = 'admin') => {
54
+ export const addProjectMember = async (identityId: string, projectSlug: string, membership: Acl.Membership = { role: 'admin', variables: [] }) => {
54
55
  await executeGraphql(
55
56
  '/tenant',
56
57
  gql`
57
- mutation ($identity: String!, $projectSlug: String!, $role: String!) {
58
- addProjectMember(identityId: $identity, projectSlug: $projectSlug, memberships: [{ role: $role, variables: [] }]) {
58
+ mutation ($identity: String!, $projectSlug: String!, $membership: MembershipInput!) {
59
+ addProjectMember(identityId: $identity, projectSlug: $projectSlug, memberships: [$membership]) {
59
60
  ok
61
+ error {
62
+ code
63
+ developerMessage
64
+ membershipValidation {
65
+ code
66
+ role
67
+ variable
68
+ }
69
+ }
60
70
  }
61
71
  }
62
72
  `,
63
73
  {
64
- variables: { identity: identityId, projectSlug, role },
74
+ variables: { identity: identityId, projectSlug, membership },
65
75
  },
66
76
  )
67
77
  .expect(200)
68
78
  .expect(response => {
69
- assert.deepStrictEqual(response.body.data, { addProjectMember: { ok: true } })
79
+ assert.deepStrictEqual(response.body.data, { addProjectMember: { ok: true, error: null } })
70
80
  })
71
81
  }
File without changes
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=http.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"http.test.d.ts","sourceRoot":"","sources":["../../../tests/e2e/http.test.ts"],"names":[],"mappings":""}