@antelopejs/dms 0.5.1 → 0.5.3

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 (100) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/attachments/access.d.ts +1 -0
  3. package/dist/attachments/access.js +7 -3
  4. package/dist/attachments/access.js.map +1 -1
  5. package/dist/attachments/constraints.d.ts +4 -0
  6. package/dist/attachments/constraints.js +28 -0
  7. package/dist/attachments/constraints.js.map +1 -0
  8. package/dist/attachments/save.js +23 -12
  9. package/dist/attachments/save.js.map +1 -1
  10. package/dist/attachments/uploads.js +2 -0
  11. package/dist/attachments/uploads.js.map +1 -1
  12. package/dist/implementations/dms/page.js +69 -22
  13. package/dist/implementations/dms/page.js.map +1 -1
  14. package/dist/implementations/dms-base/search-route.js +3 -4
  15. package/dist/implementations/dms-base/search-route.js.map +1 -1
  16. package/dist/index.js +2 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/realtime/index.js +2 -0
  19. package/dist/realtime/index.js.map +1 -1
  20. package/dist/realtime/sessions.d.ts +3 -0
  21. package/dist/realtime/sessions.js +5 -0
  22. package/dist/realtime/sessions.js.map +1 -1
  23. package/dist/realtime/sse.d.ts +1 -1
  24. package/dist/realtime/sse.js +9 -3
  25. package/dist/realtime/sse.js.map +1 -1
  26. package/dist/routes/realtime.js +8 -3
  27. package/dist/routes/realtime.js.map +1 -1
  28. package/dist/test/attachment-host/native.d.ts +25 -0
  29. package/dist/test/attachment-host/native.js +54 -1
  30. package/dist/test/attachment-host/native.js.map +1 -1
  31. package/dist/test/helpers/attachments.d.ts +1 -1
  32. package/dist/test/helpers/attachments.js +2 -2
  33. package/dist/test/helpers/attachments.js.map +1 -1
  34. package/dist/test/helpers/reload-host.d.ts +7 -2
  35. package/dist/test/helpers/reload-host.js +23 -4
  36. package/dist/test/helpers/reload-host.js.map +1 -1
  37. package/dist/test/integration/files/field-constraints.test.d.ts +1 -0
  38. package/dist/test/integration/files/field-constraints.test.js +100 -0
  39. package/dist/test/integration/files/field-constraints.test.js.map +1 -0
  40. package/dist/test/integration/files/page-mode-form-files.test.d.ts +1 -0
  41. package/dist/test/integration/files/page-mode-form-files.test.js +114 -0
  42. package/dist/test/integration/files/page-mode-form-files.test.js.map +1 -0
  43. package/dist/test/integration/files/resource-form-files.test.d.ts +1 -0
  44. package/dist/test/integration/files/resource-form-files.test.js +121 -0
  45. package/dist/test/integration/files/resource-form-files.test.js.map +1 -0
  46. package/dist/test/integration/files/shared-controller-files.test.d.ts +1 -0
  47. package/dist/test/integration/files/shared-controller-files.test.js +136 -0
  48. package/dist/test/integration/files/shared-controller-files.test.js.map +1 -0
  49. package/dist/test/reload-host/index.js +27 -1
  50. package/dist/test/reload-host/index.js.map +1 -1
  51. package/dist/test/unit/implementations/dms/missing-category.test.d.ts +1 -0
  52. package/dist/test/unit/implementations/dms/missing-category.test.js +174 -0
  53. package/dist/test/unit/implementations/dms/missing-category.test.js.map +1 -0
  54. package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.d.ts +1 -0
  55. package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js +113 -0
  56. package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js.map +1 -0
  57. package/dist/test/unit/interfaces/dms/database-initialized-hook.test.d.ts +1 -0
  58. package/dist/test/unit/interfaces/dms/database-initialized-hook.test.js +92 -0
  59. package/dist/test/unit/interfaces/dms/database-initialized-hook.test.js.map +1 -0
  60. package/dist/test/unit/interfaces/dms/invite-extension.test.js +59 -0
  61. package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
  62. package/dist/test/unit/interfaces/dms/module-reload-registrations.test.js +2 -2
  63. package/dist/test/unit/interfaces/dms/module-reload-registrations.test.js.map +1 -1
  64. package/dist/test/unit/interfaces/dms/page-extension-ownership.test.d.ts +1 -0
  65. package/dist/test/unit/interfaces/dms/page-extension-ownership.test.js +153 -0
  66. package/dist/test/unit/interfaces/dms/page-extension-ownership.test.js.map +1 -0
  67. package/dist/test/unit/interfaces/dms-base/resource-form.test.js +19 -0
  68. package/dist/test/unit/interfaces/dms-base/resource-form.test.js.map +1 -1
  69. package/dist/test/unit/interfaces/dms-base/table-view-tenant-gate.test.js +2 -2
  70. package/dist/test/unit/interfaces/dms-base/table-view-tenant-gate.test.js.map +1 -1
  71. package/dist/test/unit/realtime/stop-closes-streams.test.d.ts +1 -0
  72. package/dist/test/unit/realtime/stop-closes-streams.test.js +99 -0
  73. package/dist/test/unit/realtime/stop-closes-streams.test.js.map +1 -0
  74. package/dist/test/unit/skills/dms-dev-script.test.d.ts +1 -0
  75. package/dist/test/unit/skills/dms-dev-script.test.js +137 -0
  76. package/dist/test/unit/skills/dms-dev-script.test.js.map +1 -0
  77. package/dist/validation/auth.schema.d.ts +2 -2
  78. package/frontend-vue/dms.frontend.ts +4 -3
  79. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +116 -44
  80. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +2 -0
  81. package/frontend-vue/layers/dms-ui/app/components/form/components/File.vue +50 -21
  82. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +54 -21
  83. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +4 -3
  84. package/frontend-vue/layers/dms-ui/app/composables/form/useUploadWithProgress.ts +44 -3
  85. package/frontend-vue/layers/dms-ui/app/plugins/shortcuts.ts +1 -1
  86. package/frontend-vue/layers/dms-ui/app/types/shortcuts-aggregated.d.ts +8 -0
  87. package/frontend-vue/layers/dms-ui/app/utils/metadataRetry.ts +47 -0
  88. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +3 -1
  89. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +3 -1
  90. package/frontend-vue/tests/file-unavailable.test.ts +107 -0
  91. package/frontend-vue/tests/image-hydration-ids.test.ts +87 -0
  92. package/frontend-vue/tests/image-reference-preservation.test.ts +12 -2
  93. package/frontend-vue/tests/metadata-retry.test.ts +187 -0
  94. package/frontend-vue/tests/realtime-reconnect.test.ts +215 -0
  95. package/frontend-vue/tests/shortcuts-aggregate.test.ts +41 -0
  96. package/frontend-vue/tests/upload-forbidden-headers.test.ts +52 -0
  97. package/frontend-vue/vitest.config.ts +4 -0
  98. package/package.json +2 -2
  99. package/skills/dms-dev/SKILL.md +28 -16
  100. package/skills/dms-dev/scripts/dms-dev.sh +275 -83
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const interface_file_storage_1 = require("@antelopejs/interface-file-storage");
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const chai_1 = require("chai");
9
+ const attachments_1 = require("../../helpers/attachments");
10
+ const auth_1 = require("../../helpers/auth");
11
+ const db_1 = require("../../helpers/db");
12
+ const CONTENT = Buffer.from("page-mode form file");
13
+ const METADATA = "/api/files/metadata";
14
+ const PRESIGN_URL = "/api/files/presign";
15
+ const LOCATION = "/api/native-attachments";
16
+ const FILE_FIELD = `${LOCATION}#file`;
17
+ const TABLE_SLUG = "/nativefiles";
18
+ const PROFILE_SLUG = "/settings/user/profile";
19
+ async function ownerClient() {
20
+ const owner = await (0, auth_1.registerUser)({ owner: true });
21
+ return (0, auth_1.authorizedClient)(owner.accessToken);
22
+ }
23
+ async function formPageSlug(client, kind) {
24
+ const layout = await client.get("/dms/pagelayout", {
25
+ params: { slug: TABLE_SLUG },
26
+ });
27
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
28
+ return layout.data.components.content.options.formPages[kind];
29
+ }
30
+ async function subPageUploadToken(client, slug) {
31
+ const layout = await client.get("/dms/pagelayout", { params: { slug } });
32
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
33
+ const token = (0, attachments_1.findUploadToken)(layout.data.components.form, FILE_FIELD);
34
+ if (!token)
35
+ throw new Error(`No upload token on ${slug}`);
36
+ return token;
37
+ }
38
+ async function stageFrom(client, slug) {
39
+ const upload = await (0, attachments_1.uploadAttachment)({
40
+ client,
41
+ content: CONTENT,
42
+ mimetype: "text/plain",
43
+ claims: {},
44
+ filename: "file.txt",
45
+ token: await subPageUploadToken(client, slug),
46
+ });
47
+ return upload.key;
48
+ }
49
+ async function storedUrl(client, key) {
50
+ const promoted = await client.get(METADATA, {
51
+ params: { resourceKey: (0, interface_file_storage_1.stripStagingPrefix)(key) },
52
+ });
53
+ (0, chai_1.expect)(promoted.status, JSON.stringify(promoted.data)).to.equal(200);
54
+ return promoted.data.url;
55
+ }
56
+ describe("[integration] native files submitted from page-mode TableView forms", () => {
57
+ beforeEach(db_1.resetDatabase);
58
+ it("promotes a file staged from the table's new form sub-page", async () => {
59
+ const client = await ownerClient();
60
+ const key = await stageFrom(client, await formPageSlug(client, "new"));
61
+ const saved = await client.post(`${LOCATION}/new`, { file: key });
62
+ (0, chai_1.expect)(saved.status, JSON.stringify(saved.data)).to.equal(200);
63
+ await storedUrl(client, key);
64
+ });
65
+ it("replaces a file from the table's edit form sub-page and cleans the old one", async () => {
66
+ const client = await ownerClient();
67
+ const createdKey = await stageFrom(client, await formPageSlug(client, "new"));
68
+ const created = await client.post(`${LOCATION}/new`, { file: createdKey });
69
+ (0, chai_1.expect)(created.status, JSON.stringify(created.data)).to.equal(200);
70
+ const createdUrl = await storedUrl(client, createdKey);
71
+ const editedKey = await stageFrom(client, await formPageSlug(client, "edit"));
72
+ const edited = await client.put(`${LOCATION}/edit`, { file: editedKey }, { params: { id: created.data[0] } });
73
+ (0, chai_1.expect)(edited.status, JSON.stringify(edited.data)).to.equal(200);
74
+ await storedUrl(client, editedKey);
75
+ (0, chai_1.expect)((await axios_1.default.get(createdUrl, { validateStatus: () => true })).status, "the replaced file is cleaned up").to.equal(404);
76
+ });
77
+ it("still denies a file staged by a component that does not write to the controller", async () => {
78
+ const client = await ownerClient();
79
+ const layout = await client.get("/dms/pagelayout", {
80
+ params: { slug: PROFILE_SLUG },
81
+ });
82
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
83
+ const avatar = await (0, attachments_1.uploadAttachment)({
84
+ client,
85
+ content: CONTENT,
86
+ mimetype: "image/png",
87
+ claims: {},
88
+ filename: "avatar.png",
89
+ token: (0, attachments_1.findUploadToken)(layout.data, "profile-avatar#avatar"),
90
+ });
91
+ const foreign = await client.post(`${LOCATION}/new`, {
92
+ image: { key: avatar.key },
93
+ });
94
+ (0, chai_1.expect)(foreign.status).to.equal(403);
95
+ });
96
+ });
97
+ describe("[integration] saving a native file that was never stored", () => {
98
+ beforeEach(db_1.resetDatabase);
99
+ it("answers 400 without leaking the storage key", async () => {
100
+ const client = await ownerClient();
101
+ const presigned = await client.post(PRESIGN_URL, {
102
+ filename: "never-uploaded.txt",
103
+ size: CONTENT.byteLength,
104
+ mimetype: "text/plain",
105
+ uploadToken: await (0, attachments_1.nativeUploadToken)(client),
106
+ });
107
+ (0, chai_1.expect)(presigned.status, JSON.stringify(presigned.data)).to.equal(200);
108
+ const key = presigned.data.resourceKey;
109
+ const saved = await client.post(`${LOCATION}/new`, { file: key });
110
+ (0, chai_1.expect)(saved.status, JSON.stringify(saved.data)).to.equal(400);
111
+ (0, chai_1.expect)(JSON.stringify(saved.data)).to.not.include((0, interface_file_storage_1.stripStagingPrefix)(key));
112
+ });
113
+ });
114
+ //# sourceMappingURL=page-mode-form-files.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-mode-form-files.test.js","sourceRoot":"","sources":["../../../../src/test/integration/files/page-mode-form-files.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const interface_file_storage_1 = require("@antelopejs/interface-file-storage");
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const chai_1 = require("chai");
9
+ const attachments_1 = require("../../helpers/attachments");
10
+ const auth_1 = require("../../helpers/auth");
11
+ const db_1 = require("../../helpers/db");
12
+ const CONTENT = Buffer.from("resource-form file");
13
+ const METADATA = "/api/files/metadata";
14
+ const PRESIGN_URL = "/api/files/presign";
15
+ const LOCATION = "/api/native-attachments";
16
+ const FILE_FIELD = `${LOCATION}#file`;
17
+ const NEW_FORM_SLUG = "/nativefiles-new-form";
18
+ const EDIT_FORM_SLUG = "/nativefiles-edit-form";
19
+ const PROFILE_SLUG = "/settings/user/profile";
20
+ const FIELD_MAX_SIZE = 64;
21
+ async function ownerClient() {
22
+ const owner = await (0, auth_1.registerUser)({ owner: true });
23
+ return (0, auth_1.authorizedClient)(owner.accessToken);
24
+ }
25
+ async function formUploadToken(client, slug) {
26
+ const layout = await client.get("/dms/pagelayout", { params: { slug } });
27
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
28
+ const token = (0, attachments_1.findUploadToken)(layout.data.components.content, FILE_FIELD);
29
+ if (!token)
30
+ throw new Error(`No upload token on ${slug}`);
31
+ return token;
32
+ }
33
+ async function stageFrom(client, slug) {
34
+ const upload = await (0, attachments_1.uploadAttachment)({
35
+ client,
36
+ content: CONTENT,
37
+ mimetype: "text/plain",
38
+ claims: {},
39
+ filename: "file.txt",
40
+ token: await formUploadToken(client, slug),
41
+ });
42
+ return upload.key;
43
+ }
44
+ async function storedUrl(client, key) {
45
+ const promoted = await client.get(METADATA, {
46
+ params: { resourceKey: (0, interface_file_storage_1.stripStagingPrefix)(key) },
47
+ });
48
+ (0, chai_1.expect)(promoted.status, JSON.stringify(promoted.data)).to.equal(200);
49
+ return promoted.data.url;
50
+ }
51
+ describe("[integration] native files submitted from ResourceForm blocks", () => {
52
+ beforeEach(db_1.resetDatabase);
53
+ it("promotes a file staged from a new ResourceForm", async () => {
54
+ const client = await ownerClient();
55
+ const key = await stageFrom(client, NEW_FORM_SLUG);
56
+ const saved = await client.post(`${LOCATION}/new`, { file: key });
57
+ (0, chai_1.expect)(saved.status, JSON.stringify(saved.data)).to.equal(200);
58
+ await storedUrl(client, key);
59
+ });
60
+ it("promotes a file staged from an edit ResourceForm over a TableView's row", async () => {
61
+ const client = await ownerClient();
62
+ const tableKey = (await (0, attachments_1.uploadAttachment)({
63
+ client,
64
+ content: CONTENT,
65
+ mimetype: "text/plain",
66
+ claims: {},
67
+ filename: "table.txt",
68
+ token: await (0, attachments_1.nativeUploadToken)(client),
69
+ })).key;
70
+ const created = await client.post(`${LOCATION}/new`, { file: tableKey });
71
+ (0, chai_1.expect)(created.status, JSON.stringify(created.data)).to.equal(200);
72
+ const tableUrl = await storedUrl(client, tableKey);
73
+ const formKey = await stageFrom(client, EDIT_FORM_SLUG);
74
+ const edited = await client.put(`${LOCATION}/edit`, { file: formKey }, { params: { id: created.data[0] } });
75
+ (0, chai_1.expect)(edited.status, JSON.stringify(edited.data)).to.equal(200);
76
+ await storedUrl(client, formKey);
77
+ (0, chai_1.expect)((await axios_1.default.get(tableUrl, { validateStatus: () => true })).status, "the replaced file is cleaned up").to.equal(404);
78
+ });
79
+ it("deletes a row holding a ResourceForm file through the shared delete route", async () => {
80
+ const client = await ownerClient();
81
+ const key = await stageFrom(client, NEW_FORM_SLUG);
82
+ const saved = await client.post(`${LOCATION}/new`, { file: key });
83
+ (0, chai_1.expect)(saved.status, JSON.stringify(saved.data)).to.equal(200);
84
+ const url = await storedUrl(client, key);
85
+ const removed = await client.delete(`${LOCATION}/delete`, {
86
+ params: { id: saved.data[0] },
87
+ });
88
+ (0, chai_1.expect)(removed.status, JSON.stringify(removed.data)).to.equal(200);
89
+ (0, chai_1.expect)((await axios_1.default.get(url, { validateStatus: () => true })).status).to.equal(404);
90
+ });
91
+ it("still denies a file staged by a component that does not write to the controller", async () => {
92
+ const client = await ownerClient();
93
+ const layout = await client.get("/dms/pagelayout", {
94
+ params: { slug: PROFILE_SLUG },
95
+ });
96
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
97
+ const avatar = await (0, attachments_1.uploadAttachment)({
98
+ client,
99
+ content: CONTENT,
100
+ mimetype: "image/png",
101
+ claims: {},
102
+ filename: "avatar.png",
103
+ token: (0, attachments_1.findUploadToken)(layout.data, "profile-avatar#avatar"),
104
+ });
105
+ const foreign = await client.post(`${LOCATION}/new`, {
106
+ image: { key: avatar.key },
107
+ });
108
+ (0, chai_1.expect)(foreign.status).to.equal(403);
109
+ });
110
+ it("applies the column's constraints at presign for a ResourceForm field", async () => {
111
+ const client = await ownerClient();
112
+ const response = await client.post(PRESIGN_URL, {
113
+ filename: "large.txt",
114
+ size: FIELD_MAX_SIZE + 1,
115
+ mimetype: "text/plain",
116
+ uploadToken: await formUploadToken(client, NEW_FORM_SLUG),
117
+ });
118
+ (0, chai_1.expect)(response.status).to.equal(400);
119
+ });
120
+ });
121
+ //# sourceMappingURL=resource-form-files.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-form-files.test.js","sourceRoot":"","sources":["../../../../src/test/integration/files/resource-form-files.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
4
+ const interface_file_storage_1 = require("@antelopejs/interface-file-storage");
5
+ const chai_1 = require("chai");
6
+ const constants_1 = require("@antelopejs/interface-dms/constants");
7
+ const db_1 = require("@antelopejs/interface-dms/db");
8
+ const upload_token_1 = require("../../../utils/upload-token");
9
+ const attachments_1 = require("../../helpers/attachments");
10
+ const auth_1 = require("../../helpers/auth");
11
+ const db_2 = require("../../helpers/db");
12
+ const CONTENT = Buffer.from("shared-controller file");
13
+ const METADATA = "/api/files/metadata";
14
+ const LOCATION = "/api/native-attachments";
15
+ const FIRST_TABLE_SLUG = "/nativefiles";
16
+ const LAST_TABLE_SLUG = "/nativefiles-secondary";
17
+ const PROFILE_SLUG = "/settings/user/profile";
18
+ const RELATION_INPUT = `${LOCATION}/form/relation`;
19
+ async function ownerClient() {
20
+ const owner = await (0, auth_1.registerUser)({ owner: true });
21
+ return (0, auth_1.authorizedClient)(owner.accessToken);
22
+ }
23
+ async function stageFrom(client, slug) {
24
+ const token = await (0, attachments_1.nativeUploadToken)(client, "file", "new", slug);
25
+ const upload = await (0, attachments_1.uploadAttachment)({
26
+ client,
27
+ content: CONTENT,
28
+ mimetype: "text/plain",
29
+ claims: {},
30
+ filename: "file.txt",
31
+ token,
32
+ });
33
+ return upload.key;
34
+ }
35
+ async function tableClaims(client, slug) {
36
+ const claims = (0, upload_token_1.verifyUploadToken)(await (0, attachments_1.nativeUploadToken)(client, "file", "new", slug));
37
+ if (!claims?.pageId || !claims.componentId)
38
+ throw new Error(`No native claims on ${slug}`);
39
+ return { pageId: claims.pageId, componentId: claims.componentId };
40
+ }
41
+ describe("[integration] native files on a data controller shared by several TableViews", () => {
42
+ beforeEach(db_2.resetDatabase);
43
+ for (const slug of [FIRST_TABLE_SLUG, LAST_TABLE_SLUG]) {
44
+ it(`promotes a file staged from the TableView on ${slug}`, async () => {
45
+ const client = await ownerClient();
46
+ const key = await stageFrom(client, slug);
47
+ const saved = await client.post(`${LOCATION}/new`, { file: key });
48
+ (0, chai_1.expect)(saved.status, JSON.stringify(saved.data)).to.equal(200);
49
+ const promoted = await client.get(METADATA, {
50
+ params: { resourceKey: (0, interface_file_storage_1.stripStagingPrefix)(key) },
51
+ });
52
+ (0, chai_1.expect)(promoted.status, JSON.stringify(promoted.data)).to.equal(200);
53
+ });
54
+ }
55
+ it("still denies a file staged by a component that is no TableView of the controller", async () => {
56
+ const client = await ownerClient();
57
+ const layout = await client.get("/dms/pagelayout", {
58
+ params: { slug: PROFILE_SLUG },
59
+ });
60
+ (0, chai_1.expect)(layout.status, JSON.stringify(layout.data)).to.equal(200);
61
+ const token = (0, attachments_1.findUploadToken)(layout.data, "profile-avatar#avatar");
62
+ (0, chai_1.expect)(token).to.be.a("string");
63
+ const image = await (0, attachments_1.uploadAttachment)({
64
+ client,
65
+ content: CONTENT,
66
+ mimetype: "image/png",
67
+ claims: {},
68
+ filename: "avatar.png",
69
+ token,
70
+ });
71
+ const foreign = await client.post(`${LOCATION}/new`, {
72
+ image: { key: image.key },
73
+ });
74
+ (0, chai_1.expect)(foreign.status).to.equal(403);
75
+ (0, chai_1.expect)((await client.get(METADATA, { params: { resourceKey: image.key } }))
76
+ .status).to.equal(200);
77
+ });
78
+ it("lets a user granted add on the first TableView only create a row with an image", async () => {
79
+ const owner = await ownerClient();
80
+ const firstTable = await tableClaims(owner, FIRST_TABLE_SLUG);
81
+ const roles = (0, interface_database_decorators_1.GetModel)(db_1.RoleModel, constants_1.DEFAULT_TENANT_ID);
82
+ const [firstTableEditor] = await roles.insert({
83
+ name: "First table editor",
84
+ permissions: [
85
+ firstTable.pageId,
86
+ firstTable.componentId,
87
+ `${firstTable.componentId}.add`,
88
+ ],
89
+ });
90
+ const editor = await (0, auth_1.registerUser)({ roles_ids: [firstTableEditor] });
91
+ const client = (0, auth_1.authorizedClient)(editor.accessToken);
92
+ const image = await (0, attachments_1.uploadAttachment)({
93
+ client,
94
+ content: CONTENT,
95
+ mimetype: "image/png",
96
+ claims: {},
97
+ filename: "image.png",
98
+ token: await (0, attachments_1.nativeUploadToken)(client, "image", "new", FIRST_TABLE_SLUG),
99
+ });
100
+ const created = await client.post(`${LOCATION}/new`, { image: { en: { key: image.key } } }, { headers: { "x-content-language": "*" } });
101
+ (0, chai_1.expect)(created.status, JSON.stringify(created.data)).to.equal(200);
102
+ const promoted = await client.get(METADATA, {
103
+ params: { resourceKey: (0, interface_file_storage_1.stripStagingPrefix)(image.key) },
104
+ });
105
+ (0, chai_1.expect)(promoted.status, JSON.stringify(promoted.data)).to.equal(200);
106
+ });
107
+ it("refuses a user granted add on none of the controller's TableViews", async () => {
108
+ const owner = await ownerClient();
109
+ const firstTable = await tableClaims(owner, FIRST_TABLE_SLUG);
110
+ const lastTable = await tableClaims(owner, LAST_TABLE_SLUG);
111
+ const [viewer] = await (0, interface_database_decorators_1.GetModel)(db_1.RoleModel, constants_1.DEFAULT_TENANT_ID).insert({
112
+ name: "Table viewer",
113
+ permissions: [
114
+ firstTable.pageId,
115
+ firstTable.componentId,
116
+ lastTable.pageId,
117
+ lastTable.componentId,
118
+ ],
119
+ });
120
+ const user = await (0, auth_1.registerUser)({ roles_ids: [viewer] });
121
+ const refused = await (0, auth_1.authorizedClient)(user.accessToken).post(`${LOCATION}/new`, { readerId: "table-viewer" });
122
+ (0, chai_1.expect)(refused.status).to.equal(403);
123
+ });
124
+ it("offers a relation's inline add to the add grant of every TableView", async () => {
125
+ const owner = await ownerClient();
126
+ const firstTable = await tableClaims(owner, FIRST_TABLE_SLUG);
127
+ const lastTable = await tableClaims(owner, LAST_TABLE_SLUG);
128
+ const relation = await owner.get(RELATION_INPUT);
129
+ (0, chai_1.expect)(relation.status, JSON.stringify(relation.data)).to.equal(200);
130
+ (0, chai_1.expect)(relation.data.options.addPermissionIds).to.have.members([
131
+ `${firstTable.componentId}.add`,
132
+ `${lastTable.componentId}.add`,
133
+ ]);
134
+ });
135
+ });
136
+ //# sourceMappingURL=shared-controller-files.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-controller-files.test.js","sourceRoot":"","sources":["../../../../src/test/integration/files/shared-controller-files.test.ts"],"names":[],"mappings":"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"}
@@ -2,31 +2,57 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.construct = construct;
4
4
  const node_crypto_1 = require("node:crypto");
5
+ const modules_1 = require("@antelopejs/interface-core/modules");
6
+ const chart_1 = require("@antelopejs/interface-dms/base/chart");
5
7
  const table_view_1 = require("@antelopejs/interface-dms/base/table-view");
6
8
  const hooks_1 = require("@antelopejs/interface-dms/hooks");
9
+ const page_1 = require("@antelopejs/interface-dms/page");
7
10
  require("./package.json");
8
11
  const PROBE_KEY = Symbol.for("@antelopejs/dms-test/reload-host");
9
12
  const PROBE_TENANT = "reload-host-tenant";
10
13
  const PROBE_LOCATION = "/reload-host/rows";
14
+ const EXTENSION_KEY = "injectedTrend";
15
+ const EXTENSION_TOPIC = "reload-host:extension";
11
16
  const generation = (0, node_crypto_1.randomUUID)();
12
17
  function probe() {
13
18
  const holder = globalThis;
14
- holder[PROBE_KEY] ??= { generations: [], calls: [] };
19
+ holder[PROBE_KEY] ??= {
20
+ generations: [],
21
+ calls: [],
22
+ owners: [],
23
+ extendedPages: [],
24
+ };
15
25
  return holder[PROBE_KEY];
16
26
  }
17
27
  function record(source) {
18
28
  probe().calls.push({ generation, source });
19
29
  }
30
+ function extendPages() {
31
+ for (const targetPageId of probe().extendedPages) {
32
+ class ReloadHostExtension {
33
+ static [EXTENSION_KEY] = (0, chart_1.ChartLine)({
34
+ realtimeTopic: EXTENSION_TOPIC,
35
+ }).meta({ name: "Injected trend" });
36
+ }
37
+ (0, page_1.RegisterPageExtension)(targetPageId)(ReloadHostExtension);
38
+ }
39
+ }
20
40
  function construct() {
21
41
  probe().generations.push(generation);
42
+ probe().owners.push((0, modules_1.GetModuleContext)()?.owner ?? generation);
22
43
  (0, hooks_1.RegisterHook)(hooks_1.Hook.MEMBER_BEING_ADDED, (payload) => {
23
44
  if (payload.tenantId === PROBE_TENANT)
24
45
  record("hook");
25
46
  return undefined;
26
47
  });
48
+ (0, hooks_1.RegisterHook)(hooks_1.Hook.DATABASE_INITIALIZED, () => {
49
+ record("database-initialized");
50
+ return undefined;
51
+ });
27
52
  (0, table_view_1.registerRealtimeMutationListener)((context) => {
28
53
  if (context.controllerLocation === PROBE_LOCATION)
29
54
  record("listener");
30
55
  });
56
+ extendPages();
31
57
  }
32
58
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/test/reload-host/index.ts"],"names":[],"mappings":";;AA6CA,8BASC;AAtDD,6CAAyC;AACzC,0EAA6F;AAC7F,2DAAqE;AAIrE,0BAAwB;AAKxB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AACjE,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAC1C,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAe3C,MAAM,UAAU,GAAG,IAAA,wBAAU,GAAE,CAAC;AAEhC,SAAS,KAAK;IACZ,MAAM,MAAM,GAAG,UAA+C,CAAC;IAC/D,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACrD,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,MAAM,CAAC,MAAmB;IACjC,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7C,CAAC;AAOD,SAAgB,SAAS;IACvB,KAAK,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrC,IAAA,oBAAY,EAAC,YAAI,CAAC,kBAAkB,EAAE,CAAC,OAAO,EAAE,EAAE;QAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,YAAY;YAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,IAAA,6CAAgC,EAAC,CAAC,OAAO,EAAE,EAAE;QAC3C,IAAI,OAAO,CAAC,kBAAkB,KAAK,cAAc;YAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/test/reload-host/index.ts"],"names":[],"mappings":";;AAsEA,8BAeC;AArFD,6CAAyC;AACzC,gEAAsE;AACtE,gEAAiE;AACjE,0EAA6F;AAC7F,2DAAqE;AACrE,yDAAuE;AAIvE,0BAAwB;AAKxB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AACjE,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAC1C,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAC3C,MAAM,aAAa,GAAG,eAAe,CAAC;AACtC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAiBhD,MAAM,UAAU,GAAG,IAAA,wBAAU,GAAE,CAAC;AAEhC,SAAS,KAAK;IACZ,MAAM,MAAM,GAAG,UAA+C,CAAC;IAC/D,MAAM,CAAC,SAAS,CAAC,KAAK;QACpB,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,EAAE;KAClB,CAAC;IACF,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,MAAM,CAAC,MAAmB;IACjC,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7C,CAAC;AAID,SAAS,WAAW;IAClB,KAAK,MAAM,YAAY,IAAI,KAAK,EAAE,CAAC,aAAa,EAAE,CAAC;QACjD,MAAM,mBAAmB;YACvB,MAAM,CAAC,CAAC,aAAa,CAAC,GAAG,IAAA,iBAAS,EAAC;gBACjC,aAAa,EAAE,eAAe;aAC/B,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;;QAEtC,IAAA,4BAAqB,EAAC,YAAY,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAOD,SAAgB,SAAS;IACvB,KAAK,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAA,0BAAgB,GAAE,EAAE,KAAK,IAAI,UAAU,CAAC,CAAC;IAC7D,IAAA,oBAAY,EAAC,YAAI,CAAC,kBAAkB,EAAE,CAAC,OAAO,EAAE,EAAE;QAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,YAAY;YAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,IAAA,6CAAgC,EAAC,CAAC,OAAO,EAAE,EAAE;QAC3C,IAAI,OAAO,CAAC,kBAAkB,KAAK,cAAc;YAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IACH,WAAW,EAAE,CAAC;AAChB,CAAC"}