@webiny/app-headless-cms 6.1.0-beta.3 → 6.2.0-beta.0

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 (172) hide show
  1. package/HeadlessCMS.js +5 -2
  2. package/HeadlessCMS.js.map +1 -1
  3. package/admin/components/ContentEntryForm/Header/Header.js +3 -6
  4. package/admin/components/ContentEntryForm/Header/Header.js.map +1 -1
  5. package/admin/components/ContentEntryForm/Header/RevisionSelector/RevisionSelector.js +1 -1
  6. package/admin/components/ContentEntryForm/Header/RevisionSelector/RevisionSelector.js.map +1 -1
  7. package/admin/contexts/Cms/index.js +32 -2
  8. package/admin/contexts/Cms/index.js.map +1 -1
  9. package/admin/hooks/usePermission.js +132 -125
  10. package/admin/hooks/usePermission.js.map +1 -1
  11. package/admin/plugins/apiInformation/index.js +3 -3
  12. package/admin/plugins/apiInformation/index.js.map +1 -1
  13. package/admin/plugins/apiInformation/placeholder.manage.graphql.d.ts +1 -0
  14. package/admin/plugins/apiInformation/placeholder.manage.graphql.js +22 -0
  15. package/admin/plugins/apiInformation/placeholder.manage.graphql.js.map +1 -0
  16. package/admin/plugins/apiInformation/placeholder.preview.graphql.d.ts +1 -0
  17. package/admin/plugins/apiInformation/placeholder.preview.graphql.js +19 -0
  18. package/admin/plugins/apiInformation/placeholder.preview.graphql.js.map +1 -0
  19. package/admin/plugins/apiInformation/placeholder.read.graphql.d.ts +1 -0
  20. package/admin/plugins/apiInformation/placeholder.read.graphql.js +20 -0
  21. package/admin/plugins/apiInformation/placeholder.read.graphql.js.map +1 -0
  22. package/admin/views/contentEntries/ContentEntriesContext.js +5 -15
  23. package/admin/views/contentEntries/ContentEntriesContext.js.map +1 -1
  24. package/admin/views/contentEntries/ContentEntriesModule.js +20 -14
  25. package/admin/views/contentEntries/ContentEntriesModule.js.map +1 -1
  26. package/admin/views/contentModels/ContentModelsDataList.js +103 -88
  27. package/admin/views/contentModels/ContentModelsDataList.js.map +1 -1
  28. package/domain/permissionsSchema.d.ts +31 -0
  29. package/domain/permissionsSchema.js +34 -0
  30. package/domain/permissionsSchema.js.map +1 -0
  31. package/exports/admin/cms.d.ts +3 -0
  32. package/exports/admin/cms.js +4 -0
  33. package/exports/admin/cms.js.map +1 -1
  34. package/features/ListCache.d.ts +29 -0
  35. package/features/ListCache.js +43 -0
  36. package/features/ListCache.js.map +1 -0
  37. package/features/contentEntry/events/EntryAfterCreateEvent.d.ts +10 -0
  38. package/features/contentEntry/events/EntryAfterCreateEvent.js +10 -0
  39. package/features/contentEntry/events/EntryAfterCreateEvent.js.map +1 -0
  40. package/features/contentEntry/events/EntryAfterDeleteEvent.d.ts +11 -0
  41. package/features/contentEntry/events/EntryAfterDeleteEvent.js +10 -0
  42. package/features/contentEntry/events/EntryAfterDeleteEvent.js.map +1 -0
  43. package/features/contentEntry/events/EntryAfterUpdateEvent.d.ts +10 -0
  44. package/features/contentEntry/events/EntryAfterUpdateEvent.js +10 -0
  45. package/features/contentEntry/events/EntryAfterUpdateEvent.js.map +1 -0
  46. package/features/contentEntry/events/abstractions.d.ts +19 -0
  47. package/features/contentEntry/events/abstractions.js +6 -0
  48. package/features/contentEntry/events/abstractions.js.map +1 -0
  49. package/features/contentEntry/events/index.d.ts +7 -0
  50. package/features/contentEntry/events/index.js +6 -0
  51. package/features/contentEntry/events/index.js.map +1 -0
  52. package/features/graphQLClient/CmsGraphQLClient.d.ts +13 -0
  53. package/features/graphQLClient/CmsGraphQLClient.js +21 -0
  54. package/features/graphQLClient/CmsGraphQLClient.js.map +1 -0
  55. package/features/graphQLClient/abstractions.d.ts +17 -0
  56. package/features/graphQLClient/abstractions.js +4 -0
  57. package/features/graphQLClient/abstractions.js.map +1 -0
  58. package/features/graphQLClient/feature.d.ts +3 -0
  59. package/features/graphQLClient/feature.js +16 -0
  60. package/features/graphQLClient/feature.js.map +1 -0
  61. package/features/graphQLClient/index.d.ts +1 -0
  62. package/features/graphQLClient/index.js +3 -0
  63. package/features/graphQLClient/index.js.map +1 -0
  64. package/features/modelGroup/abstractions.d.ts +6 -0
  65. package/features/modelGroup/abstractions.js +4 -0
  66. package/features/modelGroup/abstractions.js.map +1 -0
  67. package/features/modelGroup/createModelGroup/CreateModelGroupGateway.d.ts +23 -0
  68. package/features/modelGroup/createModelGroup/CreateModelGroupGateway.js +59 -0
  69. package/features/modelGroup/createModelGroup/CreateModelGroupGateway.js.map +1 -0
  70. package/features/modelGroup/createModelGroup/CreateModelGroupRepository.d.ts +13 -0
  71. package/features/modelGroup/createModelGroup/CreateModelGroupRepository.js +19 -0
  72. package/features/modelGroup/createModelGroup/CreateModelGroupRepository.js.map +1 -0
  73. package/features/modelGroup/createModelGroup/CreateModelGroupUseCase.d.ts +10 -0
  74. package/features/modelGroup/createModelGroup/CreateModelGroupUseCase.js +15 -0
  75. package/features/modelGroup/createModelGroup/CreateModelGroupUseCase.js.map +1 -0
  76. package/features/modelGroup/createModelGroup/abstractions.d.ts +29 -0
  77. package/features/modelGroup/createModelGroup/abstractions.js +15 -0
  78. package/features/modelGroup/createModelGroup/abstractions.js.map +1 -0
  79. package/features/modelGroup/createModelGroup/feature.d.ts +3 -0
  80. package/features/modelGroup/createModelGroup/feature.js +20 -0
  81. package/features/modelGroup/createModelGroup/feature.js.map +1 -0
  82. package/features/modelGroup/deleteModelGroup/DeleteModelGroupGateway.d.ts +21 -0
  83. package/features/modelGroup/deleteModelGroup/DeleteModelGroupGateway.js +41 -0
  84. package/features/modelGroup/deleteModelGroup/DeleteModelGroupGateway.js.map +1 -0
  85. package/features/modelGroup/deleteModelGroup/DeleteModelGroupRepository.d.ts +12 -0
  86. package/features/modelGroup/deleteModelGroup/DeleteModelGroupRepository.js +18 -0
  87. package/features/modelGroup/deleteModelGroup/DeleteModelGroupRepository.js.map +1 -0
  88. package/features/modelGroup/deleteModelGroup/DeleteModelGroupUseCase.d.ts +10 -0
  89. package/features/modelGroup/deleteModelGroup/DeleteModelGroupUseCase.js +15 -0
  90. package/features/modelGroup/deleteModelGroup/DeleteModelGroupUseCase.js.map +1 -0
  91. package/features/modelGroup/deleteModelGroup/abstractions.d.ts +21 -0
  92. package/features/modelGroup/deleteModelGroup/abstractions.js +15 -0
  93. package/features/modelGroup/deleteModelGroup/abstractions.js.map +1 -0
  94. package/features/modelGroup/deleteModelGroup/feature.d.ts +3 -0
  95. package/features/modelGroup/deleteModelGroup/feature.js +20 -0
  96. package/features/modelGroup/deleteModelGroup/feature.js.map +1 -0
  97. package/features/modelGroup/feature.d.ts +1 -0
  98. package/features/modelGroup/feature.js +21 -0
  99. package/features/modelGroup/feature.js.map +1 -0
  100. package/features/modelGroup/getModelGroup/GetModelGroupGateway.d.ts +22 -0
  101. package/features/modelGroup/getModelGroup/GetModelGroupGateway.js +55 -0
  102. package/features/modelGroup/getModelGroup/GetModelGroupGateway.js.map +1 -0
  103. package/features/modelGroup/getModelGroup/GetModelGroupRepository.d.ts +12 -0
  104. package/features/modelGroup/getModelGroup/GetModelGroupRepository.js +19 -0
  105. package/features/modelGroup/getModelGroup/GetModelGroupRepository.js.map +1 -0
  106. package/features/modelGroup/getModelGroup/GetModelGroupUseCase.d.ts +10 -0
  107. package/features/modelGroup/getModelGroup/GetModelGroupUseCase.js +15 -0
  108. package/features/modelGroup/getModelGroup/GetModelGroupUseCase.js.map +1 -0
  109. package/features/modelGroup/getModelGroup/abstractions.d.ts +22 -0
  110. package/features/modelGroup/getModelGroup/abstractions.js +15 -0
  111. package/features/modelGroup/getModelGroup/abstractions.js.map +1 -0
  112. package/features/modelGroup/getModelGroup/feature.d.ts +3 -0
  113. package/features/modelGroup/getModelGroup/feature.js +20 -0
  114. package/features/modelGroup/getModelGroup/feature.js.map +1 -0
  115. package/features/modelGroup/listModelGroups/ListModelGroupsGateway.d.ts +19 -0
  116. package/features/modelGroup/listModelGroups/ListModelGroupsGateway.js +56 -0
  117. package/features/modelGroup/listModelGroups/ListModelGroupsGateway.js.map +1 -0
  118. package/features/modelGroup/listModelGroups/ListModelGroupsRepository.d.ts +12 -0
  119. package/features/modelGroup/listModelGroups/ListModelGroupsRepository.js +23 -0
  120. package/features/modelGroup/listModelGroups/ListModelGroupsRepository.js.map +1 -0
  121. package/features/modelGroup/listModelGroups/ListModelGroupsUseCase.d.ts +10 -0
  122. package/features/modelGroup/listModelGroups/ListModelGroupsUseCase.js +15 -0
  123. package/features/modelGroup/listModelGroups/ListModelGroupsUseCase.js.map +1 -0
  124. package/features/modelGroup/listModelGroups/abstractions.d.ts +39 -0
  125. package/features/modelGroup/listModelGroups/abstractions.js +15 -0
  126. package/features/modelGroup/listModelGroups/abstractions.js.map +1 -0
  127. package/features/modelGroup/listModelGroups/feature.d.ts +3 -0
  128. package/features/modelGroup/listModelGroups/feature.js +20 -0
  129. package/features/modelGroup/listModelGroups/feature.js.map +1 -0
  130. package/features/modelGroup/updateModelGroup/UpdateModelGroupGateway.d.ts +24 -0
  131. package/features/modelGroup/updateModelGroup/UpdateModelGroupGateway.js +56 -0
  132. package/features/modelGroup/updateModelGroup/UpdateModelGroupGateway.js.map +1 -0
  133. package/features/modelGroup/updateModelGroup/UpdateModelGroupRepository.d.ts +13 -0
  134. package/features/modelGroup/updateModelGroup/UpdateModelGroupRepository.js +31 -0
  135. package/features/modelGroup/updateModelGroup/UpdateModelGroupRepository.js.map +1 -0
  136. package/features/modelGroup/updateModelGroup/UpdateModelGroupUseCase.d.ts +10 -0
  137. package/features/modelGroup/updateModelGroup/UpdateModelGroupUseCase.js +15 -0
  138. package/features/modelGroup/updateModelGroup/UpdateModelGroupUseCase.js.map +1 -0
  139. package/features/modelGroup/updateModelGroup/abstractions.d.ts +30 -0
  140. package/features/modelGroup/updateModelGroup/abstractions.js +15 -0
  141. package/features/modelGroup/updateModelGroup/abstractions.js.map +1 -0
  142. package/features/modelGroup/updateModelGroup/feature.d.ts +3 -0
  143. package/features/modelGroup/updateModelGroup/feature.js +20 -0
  144. package/features/modelGroup/updateModelGroup/feature.js.map +1 -0
  145. package/features/permissions/abstractions.d.ts +17 -0
  146. package/features/permissions/abstractions.js +5 -0
  147. package/features/permissions/abstractions.js.map +1 -0
  148. package/features/permissions/feature.d.ts +14 -0
  149. package/features/permissions/feature.js +6 -0
  150. package/features/permissions/feature.js.map +1 -0
  151. package/package.json +29 -30
  152. package/presentation/modelGroup/hooks/index.d.ts +5 -0
  153. package/presentation/modelGroup/hooks/index.js +7 -0
  154. package/presentation/modelGroup/hooks/index.js.map +1 -0
  155. package/presentation/modelGroup/hooks/useCreateModelGroup.d.ts +4 -0
  156. package/presentation/modelGroup/hooks/useCreateModelGroup.js +12 -0
  157. package/presentation/modelGroup/hooks/useCreateModelGroup.js.map +1 -0
  158. package/presentation/modelGroup/hooks/useDeleteModelGroup.d.ts +3 -0
  159. package/presentation/modelGroup/hooks/useDeleteModelGroup.js +12 -0
  160. package/presentation/modelGroup/hooks/useDeleteModelGroup.js.map +1 -0
  161. package/presentation/modelGroup/hooks/useGetModelGroup.d.ts +3 -0
  162. package/presentation/modelGroup/hooks/useGetModelGroup.js +12 -0
  163. package/presentation/modelGroup/hooks/useGetModelGroup.js.map +1 -0
  164. package/presentation/modelGroup/hooks/useListModelGroups.d.ts +3 -0
  165. package/presentation/modelGroup/hooks/useListModelGroups.js +16 -0
  166. package/presentation/modelGroup/hooks/useListModelGroups.js.map +1 -0
  167. package/presentation/modelGroup/hooks/useUpdateModelGroup.d.ts +4 -0
  168. package/presentation/modelGroup/hooks/useUpdateModelGroup.js +12 -0
  169. package/presentation/modelGroup/hooks/useUpdateModelGroup.js.map +1 -0
  170. package/admin/plugins/apiInformation/placeholder.manage.graphql +0 -18
  171. package/admin/plugins/apiInformation/placeholder.preview.graphql +0 -15
  172. package/admin/plugins/apiInformation/placeholder.read.graphql +0 -16
@@ -1,26 +1,108 @@
1
- import { useCallback, useMemo } from "react";
1
+ import { useCallback, useContext, useMemo } from "react";
2
2
  import { useIdentity } from "@webiny/app-admin";
3
3
  import { makeDecoratable } from "@webiny/react-composition";
4
+ import { ModelContext } from "@webiny/app-headless-cms-common/ModelProvider/ModelContext.js";
5
+ function isModelAllowed(modelPermissions, modelId) {
6
+ // No model permissions in this group means all models are allowed.
7
+ if (!modelPermissions.length) {
8
+ return true;
9
+ }
10
+ for (const permission of modelPermissions) {
11
+ // If no models array, this permission grants access to all models.
12
+ if (!Array.isArray(permission.models)) {
13
+ return true;
14
+ }
15
+ if (permission.models.includes(modelId)) {
16
+ return true;
17
+ }
18
+ }
19
+ return false;
20
+ }
21
+ function isGroupAllowed(groupPermissions, groupId) {
22
+ // No group permissions in this group means all groups are allowed.
23
+ if (!groupPermissions.length) {
24
+ return true;
25
+ }
26
+ for (const permission of groupPermissions) {
27
+ // If no groups array, this permission grants access to all groups.
28
+ if (!Array.isArray(permission.groups)) {
29
+ return true;
30
+ }
31
+ if (permission.groups.includes(groupId)) {
32
+ return true;
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ /**
38
+ * Check if any _src group grants access for the given model.
39
+ */
40
+ function hasAccessForModel({
41
+ permissions,
42
+ modelPermissions,
43
+ modelId,
44
+ check
45
+ }) {
46
+ const srcKeys = new Set();
47
+ for (const p of [...permissions, ...modelPermissions]) {
48
+ srcKeys.add(p._src);
49
+ }
50
+ for (const src of srcKeys) {
51
+ const srcPerms = permissions.filter(p => p._src === src);
52
+ const srcModelPerms = modelPermissions.filter(p => p._src === src);
53
+ if (!srcPerms.length) {
54
+ continue;
55
+ }
56
+ if (!srcPerms.some(check)) {
57
+ continue;
58
+ }
59
+ const modelAllowed = isModelAllowed(srcModelPerms, modelId);
60
+ if (!modelAllowed) {
61
+ continue;
62
+ }
63
+ return true;
64
+ }
65
+ return false;
66
+ }
4
67
  export const usePermission = makeDecoratable(() => {
5
68
  const {
6
69
  identity
7
70
  } = useIdentity();
71
+ const model = useContext(ModelContext);
72
+ const modelId = model?.modelId;
8
73
  const hasFullAccess = useMemo(() => !!identity.getPermission("cms.*"), [identity]);
9
- const canRead = useCallback(permissionName => {
74
+ const modelPermissions = useMemo(() => identity.getPermissions("cms.contentModel") ?? [], [identity]);
75
+
76
+ /**
77
+ * Check permissions with _src-based model scoping when a model context is available.
78
+ * When no model context exists, falls back to checking permissions without model correlation.
79
+ */
80
+ const checkPermission = useCallback((permissionName, check) => {
10
81
  if (hasFullAccess) {
11
82
  return true;
12
83
  }
13
- const permissions = identity.getPermissions(permissionName) ?? [];
84
+ const permissions = identity.getPermissions(permissionName);
14
85
  if (!permissions.length) {
15
86
  return false;
16
87
  }
17
- return permissions.some(permission => {
88
+ if (modelId) {
89
+ return hasAccessForModel({
90
+ permissions,
91
+ modelPermissions,
92
+ modelId,
93
+ check
94
+ });
95
+ }
96
+ return permissions.some(check);
97
+ }, [identity, hasFullAccess, modelId, modelPermissions]);
98
+ const canRead = useCallback(permissionName => {
99
+ return checkPermission(permissionName, permission => {
18
100
  if (typeof permission.rwd !== "string") {
19
101
  return true;
20
102
  }
21
103
  return permission.rwd.includes("r");
22
104
  });
23
- }, [identity, hasFullAccess]);
105
+ }, [checkPermission]);
24
106
  const canReadEntries = useCallback(({
25
107
  contentModelGroup,
26
108
  contentModel
@@ -28,79 +110,48 @@ export const usePermission = makeDecoratable(() => {
28
110
  if (hasFullAccess) {
29
111
  return true;
30
112
  }
31
- const permissions = identity.getPermissions("cms.contentEntry") ?? [];
32
- if (!permissions.length) {
113
+ const entryPermissions = identity.getPermissions("cms.contentEntry") ?? [];
114
+ if (!entryPermissions.length) {
33
115
  return false;
34
116
  }
117
+ const groupPermissions = identity.getPermissions("cms.contentModelGroup") ?? [];
35
118
 
36
- // Check "contentModel" list.
37
- const contentModelPermissions = identity.getPermissions("cms.contentModel");
38
-
39
- // "all" means user has access to all models.
40
- let allowedModels = [];
41
- for (let i = 0; i < contentModelPermissions.length; i++) {
42
- const permission = contentModelPermissions[i];
43
- const permissionAllowedModels = permission?.models;
44
- // The moment we encounter a permission that gives access to all models,
45
- // we can stop checking other permissions.
46
- const allModelsAllowed = !Array.isArray(permissionAllowedModels);
47
- if (allModelsAllowed) {
48
- allowedModels = "all";
49
- break;
119
+ // Group all permissions by _src. Permissions without _src go into an "ungrouped" bucket.
120
+ const srcKeys = new Set();
121
+ for (const p of [...entryPermissions, ...modelPermissions, ...groupPermissions]) {
122
+ srcKeys.add(p._src);
123
+ }
124
+ for (const src of srcKeys) {
125
+ const srcEntryPerms = entryPermissions.filter(p => p._src === src);
126
+ const srcModelPerms = modelPermissions.filter(p => p._src === src);
127
+ const srcGroupPerms = groupPermissions.filter(p => p._src === src);
128
+ if (!srcEntryPerms.length) {
129
+ continue;
50
130
  }
51
- allowedModels = [...allowedModels, ...permissionAllowedModels];
52
- }
53
- if (Array.isArray(allowedModels)) {
54
- return allowedModels.includes(contentModel.modelId);
55
- }
56
-
57
- // Check "contentModelGroup" list.
58
- const contentModelGroupPermissions = identity.getPermissions("cms.contentModelGroup");
59
-
60
- // "all" means user has access to all models.
61
- let allowedModelGroups = [];
62
- for (let i = 0; i < contentModelGroupPermissions.length; i++) {
63
- const permission = contentModelGroupPermissions[i];
64
- const permissionAllowedModelGroups = permission?.models;
65
- // The moment we encounter a permission that gives access to all models,
66
- // we can stop checking other permissions.
67
- const allModelGroupsAllowed = !Array.isArray(permissionAllowedModelGroups);
68
- if (allModelGroupsAllowed) {
69
- allowedModelGroups = "all";
70
- break;
131
+ const hasReadAccess = srcEntryPerms.some(p => {
132
+ if (typeof p.rwd !== "string") {
133
+ return true;
134
+ }
135
+ return p.rwd.includes("r");
136
+ });
137
+ if (!hasReadAccess) {
138
+ continue;
71
139
  }
72
- allowedModelGroups = [...allowedModelGroups, ...permissionAllowedModelGroups];
73
- }
74
- if (Array.isArray(allowedModelGroups)) {
75
- return allowedModelGroups.includes(contentModelGroup.id);
76
- }
77
- for (let i = 0; i < permissions.length; i++) {
78
- const permission = permissions[i];
79
-
80
- // If no RWD restrictions are set, we can return true.
81
- if (typeof permission.rwd !== "string") {
82
- return true;
140
+ const modelAllowed = isModelAllowed(srcModelPerms, contentModel.modelId);
141
+ if (!modelAllowed) {
142
+ continue;
83
143
  }
84
- const rwdGivesReadAccess = permission.rwd.includes("r");
85
- if (rwdGivesReadAccess) {
86
- return true;
144
+ const groupAllowed = isGroupAllowed(srcGroupPerms, contentModelGroup.id);
145
+ if (!groupAllowed) {
146
+ continue;
87
147
  }
148
+ return true;
88
149
  }
89
150
  return false;
90
- }, [identity, hasFullAccess]);
151
+ }, [identity, hasFullAccess, modelPermissions]);
91
152
  const canEdit = useCallback((item, permissionName) => {
92
- if (hasFullAccess) {
93
- return true;
94
- }
95
- const permissions = identity.getPermissions(permissionName);
96
- if (!permissions.length || !identity) {
97
- return false;
98
- }
99
- return permissions.some(permission => {
153
+ return checkPermission(permissionName, permission => {
100
154
  if (permission.own) {
101
- /**
102
- * There will be no "createdBy" field for a new entry therefore we enable the access.
103
- */
104
155
  if (!item.createdBy) {
105
156
  return true;
106
157
  }
@@ -115,41 +166,18 @@ export const usePermission = makeDecoratable(() => {
115
166
  }
116
167
  return false;
117
168
  });
118
- }, [identity]);
119
-
120
- /**
121
- * @description This checks whether the user has the "write" access for given permission;
122
- * without talking the "own" property in account.
123
- * @param {string} permissionName
124
- * */
169
+ }, [identity, checkPermission]);
125
170
  const canCreate = useCallback(permissionName => {
126
- if (hasFullAccess) {
127
- return true;
128
- }
129
- const permissions = identity.getPermissions(permissionName);
130
- if (!permissions.length) {
131
- return false;
132
- }
133
- return permissions.some(permission => {
171
+ return checkPermission(permissionName, permission => {
134
172
  if (typeof permission.rwd !== "string") {
135
173
  return true;
136
174
  }
137
175
  return permission.rwd.includes("w");
138
176
  });
139
- }, [identity]);
177
+ }, [checkPermission]);
140
178
  const canDelete = useCallback((item, permissionName) => {
141
- if (hasFullAccess) {
142
- return true;
143
- }
144
- const permissions = identity.getPermissions(permissionName);
145
- if (!permissions.length) {
146
- return false;
147
- }
148
- return permissions.some(permission => {
179
+ return checkPermission(permissionName, permission => {
149
180
  if (permission.own) {
150
- // Using optional chaining here because there might be cases where the item
151
- // or its `createdBy` property is not defined. In that case, we want to
152
- // return `false` and not throw an error.
153
181
  return item?.createdBy?.id === identity.id;
154
182
  }
155
183
  if (typeof permission.rwd === "string") {
@@ -157,43 +185,22 @@ export const usePermission = makeDecoratable(() => {
157
185
  }
158
186
  return false;
159
187
  });
160
- }, [identity]);
188
+ }, [identity, checkPermission]);
161
189
  const canDeleteEntries = useCallback(permissionName => {
162
- if (hasFullAccess) {
163
- return true;
164
- }
165
- const permissions = identity.getPermissions(permissionName);
166
- if (!permissions.length) {
167
- return false;
168
- }
169
- return permissions.some(permission => {
170
- return permission.rwd?.includes("d");
190
+ return checkPermission(permissionName, permission => {
191
+ return !!permission.rwd?.includes("d");
171
192
  });
172
- }, [identity, hasFullAccess]);
193
+ }, [checkPermission]);
173
194
  const canPublish = useCallback(permissionName => {
174
- if (hasFullAccess) {
175
- return true;
176
- }
177
- const permissions = identity.getPermissions(permissionName);
178
- if (!permissions.length) {
179
- return false;
180
- }
181
- return permissions.some(permission => {
182
- return permission.pw?.includes("p");
195
+ return checkPermission(permissionName, permission => {
196
+ return !!permission.pw?.includes("p");
183
197
  });
184
- }, [identity, hasFullAccess]);
198
+ }, [checkPermission]);
185
199
  const canUnpublish = useCallback(permissionName => {
186
- if (hasFullAccess) {
187
- return true;
188
- }
189
- const permissions = identity.getPermissions(permissionName);
190
- if (!permissions.length) {
191
- return false;
192
- }
193
- return permissions.some(permission => {
194
- return permission.pw?.includes("u");
200
+ return checkPermission(permissionName, permission => {
201
+ return !!permission.pw?.includes("u");
195
202
  });
196
- }, [identity, hasFullAccess]);
203
+ }, [checkPermission]);
197
204
  const canReadContentModels = canRead("cms.contentModel");
198
205
  const canReadContentModelGroups = canRead("cms.contentModelGroup");
199
206
  const canCreateContentModels = canCreate("cms.contentModel");
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useMemo","useIdentity","makeDecoratable","usePermission","identity","hasFullAccess","getPermission","canRead","permissionName","permissions","getPermissions","length","some","permission","rwd","includes","canReadEntries","contentModelGroup","contentModel","contentModelPermissions","allowedModels","i","permissionAllowedModels","models","allModelsAllowed","Array","isArray","modelId","contentModelGroupPermissions","allowedModelGroups","permissionAllowedModelGroups","allModelGroupsAllowed","id","rwdGivesReadAccess","canEdit","item","own","createdBy","canCreate","canDelete","canDeleteEntries","canPublish","pw","canUnpublish","canReadContentModels","canReadContentModelGroups","canCreateContentModels","canCreateContentModelGroups","canAccessManageEndpoint","undefined"],"sources":["usePermission.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { useIdentity } from \"@webiny/app-admin\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport type { CmsGroup, CmsIdentity, CmsModel, CmsSecurityPermission } from \"~/types.js\";\n\nexport interface CreatableItem {\n createdBy?: Pick<CmsIdentity, \"id\">;\n}\n\ninterface CanReadEntriesCallableParams {\n contentModelGroup: Pick<CmsGroup, \"id\">;\n contentModel: Pick<CmsModel, \"modelId\">;\n}\n\nexport const usePermission = makeDecoratable(() => {\n const { identity } = useIdentity();\n\n const hasFullAccess = useMemo(() => !!identity.getPermission(\"cms.*\"), [identity]);\n\n const canRead = useCallback(\n (permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n const permissions =\n identity.getPermissions<CmsSecurityPermission>(permissionName) ?? [];\n\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n\n return permission.rwd.includes(\"r\");\n });\n },\n [identity, hasFullAccess]\n );\n\n const canReadEntries = useCallback(\n ({ contentModelGroup, contentModel }: CanReadEntriesCallableParams): boolean => {\n if (hasFullAccess) {\n return true;\n }\n\n const permissions =\n identity.getPermissions<CmsSecurityPermission>(\"cms.contentEntry\") ?? [];\n if (!permissions.length) {\n return false;\n }\n\n // Check \"contentModel\" list.\n const contentModelPermissions = identity.getPermissions(\"cms.contentModel\");\n\n // \"all\" means user has access to all models.\n let allowedModels: \"all\" | string[] = [];\n\n for (let i = 0; i < contentModelPermissions.length; i++) {\n const permission = contentModelPermissions[i];\n const permissionAllowedModels = permission?.models;\n // The moment we encounter a permission that gives access to all models,\n // we can stop checking other permissions.\n const allModelsAllowed = !Array.isArray(permissionAllowedModels);\n if (allModelsAllowed) {\n allowedModels = \"all\";\n break;\n }\n\n allowedModels = [...allowedModels, ...permissionAllowedModels];\n }\n\n if (Array.isArray(allowedModels)) {\n return allowedModels.includes(contentModel.modelId);\n }\n\n // Check \"contentModelGroup\" list.\n const contentModelGroupPermissions = identity.getPermissions(\"cms.contentModelGroup\");\n\n // \"all\" means user has access to all models.\n let allowedModelGroups: \"all\" | string[] = [];\n\n for (let i = 0; i < contentModelGroupPermissions.length; i++) {\n const permission = contentModelGroupPermissions[i];\n const permissionAllowedModelGroups = permission?.models;\n // The moment we encounter a permission that gives access to all models,\n // we can stop checking other permissions.\n const allModelGroupsAllowed = !Array.isArray(permissionAllowedModelGroups);\n if (allModelGroupsAllowed) {\n allowedModelGroups = \"all\";\n break;\n }\n\n allowedModelGroups = [...allowedModelGroups, ...permissionAllowedModelGroups];\n }\n\n if (Array.isArray(allowedModelGroups)) {\n return allowedModelGroups.includes(contentModelGroup.id);\n }\n\n for (let i = 0; i < permissions.length; i++) {\n const permission = permissions[i];\n\n // If no RWD restrictions are set, we can return true.\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n\n const rwdGivesReadAccess = permission.rwd.includes(\"r\");\n if (rwdGivesReadAccess) {\n return true;\n }\n }\n\n return false;\n },\n [identity, hasFullAccess]\n );\n\n const canEdit = useCallback(\n (item: CreatableItem, permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n\n if (!permissions.length || !identity) {\n return false;\n }\n\n return permissions.some(permission => {\n if (permission.own) {\n /**\n * There will be no \"createdBy\" field for a new entry therefore we enable the access.\n */\n if (!item.createdBy) {\n return true;\n }\n\n if (item?.createdBy?.id === identity.id) {\n return true;\n }\n }\n\n if (typeof permission.rwd === \"string\") {\n if (permission.rwd.includes(\"w\")) {\n return true;\n }\n }\n\n return false;\n });\n },\n [identity]\n );\n\n /**\n * @description This checks whether the user has the \"write\" access for given permission;\n * without talking the \"own\" property in account.\n * @param {string} permissionName\n * */\n const canCreate = useCallback(\n (permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n\n return permission.rwd.includes(\"w\");\n });\n },\n [identity]\n );\n\n const canDelete = useCallback(\n (item: CreatableItem, permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n if (permission.own) {\n // Using optional chaining here because there might be cases where the item\n // or its `createdBy` property is not defined. In that case, we want to\n // return `false` and not throw an error.\n return item?.createdBy?.id === identity.id;\n }\n\n if (typeof permission.rwd === \"string\") {\n return permission.rwd.includes(\"d\");\n }\n\n return false;\n });\n },\n [identity]\n );\n\n const canDeleteEntries = useCallback(\n (permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n return permission.rwd?.includes(\"d\");\n });\n },\n [identity, hasFullAccess]\n );\n\n const canPublish = useCallback(\n (permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n return permission.pw?.includes(\"p\");\n });\n },\n [identity, hasFullAccess]\n );\n\n const canUnpublish = useCallback(\n (permissionName: string): boolean => {\n if (hasFullAccess) {\n return true;\n }\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n\n if (!permissions.length) {\n return false;\n }\n\n return permissions.some(permission => {\n return permission.pw?.includes(\"u\");\n });\n },\n [identity, hasFullAccess]\n );\n\n const canReadContentModels = canRead(\"cms.contentModel\");\n const canReadContentModelGroups = canRead(\"cms.contentModelGroup\");\n const canCreateContentModels = canCreate(\"cms.contentModel\");\n const canCreateContentModelGroups = canCreate(\"cms.contentModelGroup\");\n const canAccessManageEndpoint = useMemo(() => {\n return identity.getPermission(\"cms.endpoint.manage\") !== undefined;\n }, [identity]);\n\n return {\n canReadEntries,\n canEdit,\n canCreate,\n canDelete,\n canDeleteEntries,\n canPublish,\n canUnpublish,\n canReadContentModels,\n canReadContentModelGroups,\n canCreateContentModels,\n canCreateContentModelGroups,\n canAccessManageEndpoint\n };\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useContext","useMemo","useIdentity","makeDecoratable","ModelContext","isModelAllowed","modelPermissions","modelId","length","permission","Array","isArray","models","includes","isGroupAllowed","groupPermissions","groupId","groups","hasAccessForModel","permissions","check","srcKeys","Set","p","add","_src","src","srcPerms","filter","srcModelPerms","some","modelAllowed","usePermission","identity","model","hasFullAccess","getPermission","getPermissions","checkPermission","permissionName","canRead","rwd","canReadEntries","contentModelGroup","contentModel","entryPermissions","srcEntryPerms","srcGroupPerms","hasReadAccess","groupAllowed","id","canEdit","item","own","createdBy","canCreate","canDelete","canDeleteEntries","canPublish","pw","canUnpublish","canReadContentModels","canReadContentModelGroups","canCreateContentModels","canCreateContentModelGroups","canAccessManageEndpoint","undefined"],"sources":["usePermission.ts"],"sourcesContent":["import { useCallback, useContext, useMemo } from \"react\";\nimport { useIdentity } from \"@webiny/app-admin\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\nimport { ModelContext } from \"@webiny/app-headless-cms-common/ModelProvider/ModelContext.js\";\nimport type { CmsGroup, CmsIdentity, CmsModel, CmsSecurityPermission } from \"~/types.js\";\n\nexport interface CreatableItem {\n createdBy?: Pick<CmsIdentity, \"id\">;\n}\n\ninterface CanReadEntriesCallableParams {\n contentModelGroup: Pick<CmsGroup, \"id\">;\n contentModel: Pick<CmsModel, \"modelId\">;\n}\n\nfunction isModelAllowed(modelPermissions: CmsSecurityPermission[], modelId: string): boolean {\n // No model permissions in this group means all models are allowed.\n if (!modelPermissions.length) {\n return true;\n }\n\n for (const permission of modelPermissions) {\n // If no models array, this permission grants access to all models.\n if (!Array.isArray(permission.models)) {\n return true;\n }\n\n if (permission.models.includes(modelId)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction isGroupAllowed(groupPermissions: CmsSecurityPermission[], groupId: string): boolean {\n // No group permissions in this group means all groups are allowed.\n if (!groupPermissions.length) {\n return true;\n }\n\n for (const permission of groupPermissions) {\n // If no groups array, this permission grants access to all groups.\n if (!Array.isArray(permission.groups)) {\n return true;\n }\n\n if (permission.groups.includes(groupId)) {\n return true;\n }\n }\n\n return false;\n}\n\ninterface HasAccessParams {\n permissions: CmsSecurityPermission[];\n modelPermissions: CmsSecurityPermission[];\n modelId: string;\n check: (permission: CmsSecurityPermission) => boolean;\n}\n\n/**\n * Check if any _src group grants access for the given model.\n */\nfunction hasAccessForModel({ permissions, modelPermissions, modelId, check }: HasAccessParams) {\n const srcKeys = new Set<string | undefined>();\n for (const p of [...permissions, ...modelPermissions]) {\n srcKeys.add(p._src);\n }\n\n for (const src of srcKeys) {\n const srcPerms = permissions.filter(p => p._src === src);\n const srcModelPerms = modelPermissions.filter(p => p._src === src);\n\n if (!srcPerms.length) {\n continue;\n }\n\n if (!srcPerms.some(check)) {\n continue;\n }\n\n const modelAllowed = isModelAllowed(srcModelPerms, modelId);\n if (!modelAllowed) {\n continue;\n }\n\n return true;\n }\n\n return false;\n}\n\nexport const usePermission = makeDecoratable(() => {\n const { identity } = useIdentity();\n const model = useContext(ModelContext);\n const modelId = model?.modelId;\n\n const hasFullAccess = useMemo(() => !!identity.getPermission(\"cms.*\"), [identity]);\n\n const modelPermissions = useMemo(\n () => identity.getPermissions<CmsSecurityPermission>(\"cms.contentModel\") ?? [],\n [identity]\n );\n\n /**\n * Check permissions with _src-based model scoping when a model context is available.\n * When no model context exists, falls back to checking permissions without model correlation.\n */\n const checkPermission = useCallback(\n (permissionName: string, check: (permission: CmsSecurityPermission) => boolean) => {\n if (hasFullAccess) {\n return true;\n }\n\n const permissions = identity.getPermissions<CmsSecurityPermission>(permissionName);\n if (!permissions.length) {\n return false;\n }\n\n if (modelId) {\n return hasAccessForModel({\n permissions,\n modelPermissions,\n modelId,\n check\n });\n }\n\n return permissions.some(check);\n },\n [identity, hasFullAccess, modelId, modelPermissions]\n );\n\n const canRead = useCallback(\n (permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n return permission.rwd.includes(\"r\");\n });\n },\n [checkPermission]\n );\n\n const canReadEntries = useCallback(\n ({ contentModelGroup, contentModel }: CanReadEntriesCallableParams): boolean => {\n if (hasFullAccess) {\n return true;\n }\n\n const entryPermissions =\n identity.getPermissions<CmsSecurityPermission>(\"cms.contentEntry\") ?? [];\n if (!entryPermissions.length) {\n return false;\n }\n\n const groupPermissions =\n identity.getPermissions<CmsSecurityPermission>(\"cms.contentModelGroup\") ?? [];\n\n // Group all permissions by _src. Permissions without _src go into an \"ungrouped\" bucket.\n const srcKeys = new Set<string | undefined>();\n for (const p of [...entryPermissions, ...modelPermissions, ...groupPermissions]) {\n srcKeys.add(p._src);\n }\n\n for (const src of srcKeys) {\n const srcEntryPerms = entryPermissions.filter(p => p._src === src);\n const srcModelPerms = modelPermissions.filter(p => p._src === src);\n const srcGroupPerms = groupPermissions.filter(p => p._src === src);\n\n if (!srcEntryPerms.length) {\n continue;\n }\n\n const hasReadAccess = srcEntryPerms.some(p => {\n if (typeof p.rwd !== \"string\") {\n return true;\n }\n return p.rwd.includes(\"r\");\n });\n\n if (!hasReadAccess) {\n continue;\n }\n\n const modelAllowed = isModelAllowed(srcModelPerms, contentModel.modelId);\n if (!modelAllowed) {\n continue;\n }\n\n const groupAllowed = isGroupAllowed(srcGroupPerms, contentModelGroup.id);\n if (!groupAllowed) {\n continue;\n }\n\n return true;\n }\n\n return false;\n },\n [identity, hasFullAccess, modelPermissions]\n );\n\n const canEdit = useCallback(\n (item: CreatableItem, permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n if (permission.own) {\n if (!item.createdBy) {\n return true;\n }\n\n if (item?.createdBy?.id === identity.id) {\n return true;\n }\n }\n\n if (typeof permission.rwd === \"string\") {\n if (permission.rwd.includes(\"w\")) {\n return true;\n }\n }\n\n return false;\n });\n },\n [identity, checkPermission]\n );\n\n const canCreate = useCallback(\n (permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n return permission.rwd.includes(\"w\");\n });\n },\n [checkPermission]\n );\n\n const canDelete = useCallback(\n (item: CreatableItem, permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n if (permission.own) {\n return item?.createdBy?.id === identity.id;\n }\n\n if (typeof permission.rwd === \"string\") {\n return permission.rwd.includes(\"d\");\n }\n\n return false;\n });\n },\n [identity, checkPermission]\n );\n\n const canDeleteEntries = useCallback(\n (permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n return !!permission.rwd?.includes(\"d\");\n });\n },\n [checkPermission]\n );\n\n const canPublish = useCallback(\n (permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n return !!permission.pw?.includes(\"p\");\n });\n },\n [checkPermission]\n );\n\n const canUnpublish = useCallback(\n (permissionName: string): boolean => {\n return checkPermission(permissionName, permission => {\n return !!permission.pw?.includes(\"u\");\n });\n },\n [checkPermission]\n );\n\n const canReadContentModels = canRead(\"cms.contentModel\");\n const canReadContentModelGroups = canRead(\"cms.contentModelGroup\");\n const canCreateContentModels = canCreate(\"cms.contentModel\");\n const canCreateContentModelGroups = canCreate(\"cms.contentModelGroup\");\n const canAccessManageEndpoint = useMemo(() => {\n return identity.getPermission(\"cms.endpoint.manage\") !== undefined;\n }, [identity]);\n\n return {\n canReadEntries,\n canEdit,\n canCreate,\n canDelete,\n canDeleteEntries,\n canPublish,\n canUnpublish,\n canReadContentModels,\n canReadContentModelGroups,\n canCreateContentModels,\n canCreateContentModelGroups,\n canAccessManageEndpoint\n };\n});\n"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,6 @@
1
- const manageQuery = "# Webiny Headless CMS Manage API\n#\n# This API controls all the operations within the Headless CMS module.\n# Use it to manage content, create and modify content models and more.\n# Explore the schema for details.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content model groups:\n{\n listContentModelGroups {\n data {\n name\n icon\n slug\n }\n }\n}\n";
2
- const readQuery = "# Webiny Headless CMS Read API\n#\n# This is the API to use in your 3rd party apps to read your content.\n# It returns only content that has been published.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content models:\n{\n listContentModels {\n data {\n name\n modelId\n }\n }\n}\n";
3
- const previewQuery = "# Webiny Headless CMS Preview API\n#\n# This is the API to use in your 3rd party apps to preview content.\n# It returns the latest content revision, regardless of whether it was published or not.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content models:\n{\n listContentModels {\n data {\n name\n }\n }\n}\n";
1
+ import { manageQuery } from "./placeholder.manage.graphql.js";
2
+ import { readQuery } from "./placeholder.read.graphql.js";
3
+ import { previewQuery } from "./placeholder.preview.graphql.js";
4
4
  import { config as appConfig } from "@webiny/app/config.js";
5
5
  const plugins = [{
6
6
  type: "graphql-playground-tab",
@@ -1 +1 @@
1
- {"version":3,"names":["manageQuery","readQuery","previewQuery","config","appConfig","plugins","type","name","tab","identity","apiUrl","getKey","process","env","REACT_APP_API_URL","getPermission","endpoint","headers","query"],"sources":["index.tsx"],"sourcesContent":["import type { GraphQLPlaygroundTabPlugin } from \"@webiny/app-graphql-playground/types.js\";\nimport raw from \"raw.macro\";\nconst manageQuery = raw(\"./placeholder.manage.graphql\");\nconst readQuery = raw(\"./placeholder.read.graphql\");\nconst previewQuery = raw(\"./placeholder.preview.graphql\");\nimport { config as appConfig } from \"@webiny/app/config.js\";\n\nconst plugins: GraphQLPlaygroundTabPlugin[] = [\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-manage\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.manage\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Manage API\",\n endpoint: apiUrl + \"/cms/manage\",\n headers: {},\n query: manageQuery\n };\n }\n },\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-read\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.read\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Read API\",\n endpoint: apiUrl + \"/cms/read\",\n headers: {},\n query: readQuery\n };\n }\n },\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-preview\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.preview\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Preview API\",\n endpoint: apiUrl + \"/cms/preview\",\n headers: {},\n query: previewQuery\n };\n }\n }\n];\n\nexport default plugins;\n"],"mappings":"AAEA,MAAMA,WAAW,0eAAsC;AACvD,MAAMC,SAAS,2ZAAoC;AACnD,MAAMC,YAAY,mbAAuC;AACzD,SAASC,MAAM,IAAIC,SAAS,QAAQ,uBAAuB;AAE3D,MAAMC,OAAqC,GAAG,CAC1C;EACIC,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,+BAA+B;EACrCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,qBAAqB,CAAC,EAChD;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,2BAA2B;MACjCS,QAAQ,EAAEN,MAAM,GAAG,aAAa;MAChCO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAElB;IACX,CAAC;EACL;AACJ,CAAC,EACD;EACIM,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,6BAA6B;EACnCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,mBAAmB,CAAC,EAC9C;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,yBAAyB;MAC/BS,QAAQ,EAAEN,MAAM,GAAG,WAAW;MAC9BO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAEjB;IACX,CAAC;EACL;AACJ,CAAC,EACD;EACIK,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,gCAAgC;EACtCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,sBAAsB,CAAC,EACjD;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,4BAA4B;MAClCS,QAAQ,EAAEN,MAAM,GAAG,cAAc;MACjCO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAEhB;IACX,CAAC;EACL;AACJ,CAAC,CACJ;AAED,eAAeG,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["manageQuery","readQuery","previewQuery","config","appConfig","plugins","type","name","tab","identity","apiUrl","getKey","process","env","REACT_APP_API_URL","getPermission","endpoint","headers","query"],"sources":["index.tsx"],"sourcesContent":["import type { GraphQLPlaygroundTabPlugin } from \"@webiny/app-graphql-playground/types.js\";\nimport { manageQuery } from \"./placeholder.manage.graphql.js\";\nimport { readQuery } from \"./placeholder.read.graphql.js\";\nimport { previewQuery } from \"./placeholder.preview.graphql.js\";\nimport { config as appConfig } from \"@webiny/app/config.js\";\n\nconst plugins: GraphQLPlaygroundTabPlugin[] = [\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-manage\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.manage\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Manage API\",\n endpoint: apiUrl + \"/cms/manage\",\n headers: {},\n query: manageQuery\n };\n }\n },\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-read\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.read\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Read API\",\n endpoint: apiUrl + \"/cms/read\",\n headers: {},\n query: readQuery\n };\n }\n },\n {\n type: \"graphql-playground-tab\",\n name: \"graphql-playground-tab-preview\",\n tab({ identity }) {\n const apiUrl = appConfig.getKey(\"API_URL\", process.env.REACT_APP_API_URL);\n if (\n !identity ||\n !identity.getPermission ||\n !identity.getPermission(\"cms.endpoint.preview\")\n ) {\n return null;\n }\n\n return {\n name: \"Headless CMS - Preview API\",\n endpoint: apiUrl + \"/cms/preview\",\n headers: {},\n query: previewQuery\n };\n }\n }\n];\n\nexport default plugins;\n"],"mappings":"AACA,SAASA,WAAW;AACpB,SAASC,SAAS;AAClB,SAASC,YAAY;AACrB,SAASC,MAAM,IAAIC,SAAS,QAAQ,uBAAuB;AAE3D,MAAMC,OAAqC,GAAG,CAC1C;EACIC,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,+BAA+B;EACrCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,qBAAqB,CAAC,EAChD;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,2BAA2B;MACjCS,QAAQ,EAAEN,MAAM,GAAG,aAAa;MAChCO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAElB;IACX,CAAC;EACL;AACJ,CAAC,EACD;EACIM,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,6BAA6B;EACnCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,mBAAmB,CAAC,EAC9C;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,yBAAyB;MAC/BS,QAAQ,EAAEN,MAAM,GAAG,WAAW;MAC9BO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAEjB;IACX,CAAC;EACL;AACJ,CAAC,EACD;EACIK,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,gCAAgC;EACtCC,GAAGA,CAAC;IAAEC;EAAS,CAAC,EAAE;IACd,MAAMC,MAAM,GAAGN,SAAS,CAACO,MAAM,CAAC,SAAS,EAAEC,OAAO,CAACC,GAAG,CAACC,iBAAiB,CAAC;IACzE,IACI,CAACL,QAAQ,IACT,CAACA,QAAQ,CAACM,aAAa,IACvB,CAACN,QAAQ,CAACM,aAAa,CAAC,sBAAsB,CAAC,EACjD;MACE,OAAO,IAAI;IACf;IAEA,OAAO;MACHR,IAAI,EAAE,4BAA4B;MAClCS,QAAQ,EAAEN,MAAM,GAAG,cAAc;MACjCO,OAAO,EAAE,CAAC,CAAC;MACXC,KAAK,EAAEhB;IACX,CAAC;EACL;AACJ,CAAC,CACJ;AAED,eAAeG,OAAO","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const manageQuery = "\n # Webiny Headless CMS Manage API\n #\n # This API controls all the operations within the Headless CMS module.\n # Use it to manage content, create and modify content models and more.\n # Explore the schema for details.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content model groups:\n {\n listContentModelGroups {\n data {\n name\n icon\n slug\n }\n }\n }\n";
@@ -0,0 +1,22 @@
1
+ export const manageQuery = /* GraphQL */`
2
+ # Webiny Headless CMS Manage API
3
+ #
4
+ # This API controls all the operations within the Headless CMS module.
5
+ # Use it to manage content, create and modify content models and more.
6
+ # Explore the schema for details.
7
+ #
8
+ # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.
9
+ #
10
+ # Example query - list content model groups:
11
+ {
12
+ listContentModelGroups {
13
+ data {
14
+ name
15
+ icon
16
+ slug
17
+ }
18
+ }
19
+ }
20
+ `;
21
+
22
+ //# sourceMappingURL=placeholder.manage.graphql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["manageQuery"],"sources":["placeholder.manage.graphql.ts"],"sourcesContent":["export const manageQuery = /* GraphQL */ `\n # Webiny Headless CMS Manage API\n #\n # This API controls all the operations within the Headless CMS module.\n # Use it to manage content, create and modify content models and more.\n # Explore the schema for details.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content model groups:\n {\n listContentModelGroups {\n data {\n name\n icon\n slug\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAO,MAAMA,WAAW,GAAG,aAAc;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const previewQuery = "\n # Webiny Headless CMS Preview API\n #\n # This is the API to use in your 3rd party apps to preview content.\n # It returns the latest content revision, regardless of whether it was published or not.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content models:\n {\n listContentModels {\n data {\n name\n }\n }\n }\n";
@@ -0,0 +1,19 @@
1
+ export const previewQuery = /* GraphQL */`
2
+ # Webiny Headless CMS Preview API
3
+ #
4
+ # This is the API to use in your 3rd party apps to preview content.
5
+ # It returns the latest content revision, regardless of whether it was published or not.
6
+ #
7
+ # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.
8
+ #
9
+ # Example query - list content models:
10
+ {
11
+ listContentModels {
12
+ data {
13
+ name
14
+ }
15
+ }
16
+ }
17
+ `;
18
+
19
+ //# sourceMappingURL=placeholder.preview.graphql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["previewQuery"],"sources":["placeholder.preview.graphql.ts"],"sourcesContent":["export const previewQuery = /* GraphQL */ `\n # Webiny Headless CMS Preview API\n #\n # This is the API to use in your 3rd party apps to preview content.\n # It returns the latest content revision, regardless of whether it was published or not.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content models:\n {\n listContentModels {\n data {\n name\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAO,MAAMA,YAAY,GAAG,aAAc;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const readQuery = "\n # Webiny Headless CMS Read API\n #\n # This is the API to use in your 3rd party apps to read your content.\n # It returns only content that has been published.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content models:\n {\n listContentModels {\n data {\n name\n modelId\n }\n }\n }\n";
@@ -0,0 +1,20 @@
1
+ export const readQuery = /* GraphQL */`
2
+ # Webiny Headless CMS Read API
3
+ #
4
+ # This is the API to use in your 3rd party apps to read your content.
5
+ # It returns only content that has been published.
6
+ #
7
+ # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.
8
+ #
9
+ # Example query - list content models:
10
+ {
11
+ listContentModels {
12
+ data {
13
+ name
14
+ modelId
15
+ }
16
+ }
17
+ }
18
+ `;
19
+
20
+ //# sourceMappingURL=placeholder.read.graphql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["readQuery"],"sources":["placeholder.read.graphql.ts"],"sourcesContent":["export const readQuery = /* GraphQL */ `\n # Webiny Headless CMS Read API\n #\n # This is the API to use in your 3rd party apps to read your content.\n # It returns only content that has been published.\n #\n # Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n #\n # Example query - list content models:\n {\n listContentModels {\n data {\n name\n modelId\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAO,MAAMA,SAAS,GAAG,aAAc;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -1,5 +1,5 @@
1
- import React, { useMemo } from "react";
2
- import { useSecurity } from "@webiny/app-admin";
1
+ import React from "react";
2
+ import { usePermission } from "../../hooks/usePermission.js";
3
3
  export const ContentEntriesContext = /*#__PURE__*/React.createContext(undefined);
4
4
  export const ContentEntriesProvider = ({
5
5
  contentModel,
@@ -7,19 +7,9 @@ export const ContentEntriesProvider = ({
7
7
  insideDialog
8
8
  }) => {
9
9
  const {
10
- identity,
11
- getPermission
12
- } = useSecurity();
13
- const canCreate = useMemo(() => {
14
- const permission = getPermission("cms.contentEntry");
15
- if (!permission) {
16
- return false;
17
- }
18
- if (typeof permission.rwd !== "string") {
19
- return true;
20
- }
21
- return permission.rwd.includes("w");
22
- }, [identity]);
10
+ canCreate: canCreateEntries
11
+ } = usePermission();
12
+ const canCreate = canCreateEntries("cms.contentEntry");
23
13
  const value = {
24
14
  insideDialog,
25
15
  contentModel,
@@ -1 +1 @@
1
- {"version":3,"names":["React","useMemo","useSecurity","ContentEntriesContext","createContext","undefined","ContentEntriesProvider","contentModel","children","insideDialog","identity","getPermission","canCreate","permission","rwd","includes","value","createElement","Provider","displayName"],"sources":["ContentEntriesContext.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { useSecurity } from \"@webiny/app-admin\";\nimport type { CmsModel, CmsSecurityPermission } from \"~/types.js\";\n\nexport interface ContentEntriesContext {\n contentModel: CmsModel;\n canCreate: boolean;\n insideDialog?: boolean;\n}\n\nexport const ContentEntriesContext = React.createContext<ContentEntriesContext | undefined>(\n undefined\n);\n\nexport interface ContentEntriesContextProviderProps {\n contentModel: CmsModel;\n children: React.ReactNode;\n insideDialog?: boolean;\n}\n\nexport const ContentEntriesProvider = ({\n contentModel,\n children,\n insideDialog\n}: ContentEntriesContextProviderProps) => {\n const { identity, getPermission } = useSecurity();\n\n const canCreate = useMemo((): boolean => {\n const permission = getPermission<CmsSecurityPermission>(\"cms.contentEntry\");\n if (!permission) {\n return false;\n }\n\n if (typeof permission.rwd !== \"string\") {\n return true;\n }\n\n return permission.rwd.includes(\"w\");\n }, [identity]);\n\n const value = {\n insideDialog,\n contentModel,\n canCreate\n };\n\n return (\n <ContentEntriesContext.Provider value={value}>{children}</ContentEntriesContext.Provider>\n );\n};\n\nContentEntriesProvider.displayName = \"ContentEntriesProvider\";\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,OAAO,QAAQ,OAAO;AACtC,SAASC,WAAW,QAAQ,mBAAmB;AAS/C,OAAO,MAAMC,qBAAqB,gBAAGH,KAAK,CAACI,aAAa,CACpDC,SACJ,CAAC;AAQD,OAAO,MAAMC,sBAAsB,GAAGA,CAAC;EACnCC,YAAY;EACZC,QAAQ;EACRC;AACgC,CAAC,KAAK;EACtC,MAAM;IAAEC,QAAQ;IAAEC;EAAc,CAAC,GAAGT,WAAW,CAAC,CAAC;EAEjD,MAAMU,SAAS,GAAGX,OAAO,CAAC,MAAe;IACrC,MAAMY,UAAU,GAAGF,aAAa,CAAwB,kBAAkB,CAAC;IAC3E,IAAI,CAACE,UAAU,EAAE;MACb,OAAO,KAAK;IAChB;IAEA,IAAI,OAAOA,UAAU,CAACC,GAAG,KAAK,QAAQ,EAAE;MACpC,OAAO,IAAI;IACf;IAEA,OAAOD,UAAU,CAACC,GAAG,CAACC,QAAQ,CAAC,GAAG,CAAC;EACvC,CAAC,EAAE,CAACL,QAAQ,CAAC,CAAC;EAEd,MAAMM,KAAK,GAAG;IACVP,YAAY;IACZF,YAAY;IACZK;EACJ,CAAC;EAED,oBACIZ,KAAA,CAAAiB,aAAA,CAACd,qBAAqB,CAACe,QAAQ;IAACF,KAAK,EAAEA;EAAM,GAAER,QAAyC,CAAC;AAEjG,CAAC;AAEDF,sBAAsB,CAACa,WAAW,GAAG,wBAAwB","ignoreList":[]}
1
+ {"version":3,"names":["React","usePermission","ContentEntriesContext","createContext","undefined","ContentEntriesProvider","contentModel","children","insideDialog","canCreate","canCreateEntries","value","createElement","Provider","displayName"],"sources":["ContentEntriesContext.tsx"],"sourcesContent":["import React from \"react\";\nimport type { CmsModel } from \"~/types.js\";\nimport { usePermission } from \"~/admin/hooks/usePermission.js\";\n\nexport interface ContentEntriesContext {\n contentModel: CmsModel;\n canCreate: boolean;\n insideDialog?: boolean;\n}\n\nexport const ContentEntriesContext = React.createContext<ContentEntriesContext | undefined>(\n undefined\n);\n\nexport interface ContentEntriesContextProviderProps {\n contentModel: CmsModel;\n children: React.ReactNode;\n insideDialog?: boolean;\n}\n\nexport const ContentEntriesProvider = ({\n contentModel,\n children,\n insideDialog\n}: ContentEntriesContextProviderProps) => {\n const { canCreate: canCreateEntries } = usePermission();\n const canCreate = canCreateEntries(\"cms.contentEntry\");\n\n const value = {\n insideDialog,\n contentModel,\n canCreate\n };\n\n return (\n <ContentEntriesContext.Provider value={value}>{children}</ContentEntriesContext.Provider>\n );\n};\n\nContentEntriesProvider.displayName = \"ContentEntriesProvider\";\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,SAASC,aAAa;AAQtB,OAAO,MAAMC,qBAAqB,gBAAGF,KAAK,CAACG,aAAa,CACpDC,SACJ,CAAC;AAQD,OAAO,MAAMC,sBAAsB,GAAGA,CAAC;EACnCC,YAAY;EACZC,QAAQ;EACRC;AACgC,CAAC,KAAK;EACtC,MAAM;IAAEC,SAAS,EAAEC;EAAiB,CAAC,GAAGT,aAAa,CAAC,CAAC;EACvD,MAAMQ,SAAS,GAAGC,gBAAgB,CAAC,kBAAkB,CAAC;EAEtD,MAAMC,KAAK,GAAG;IACVH,YAAY;IACZF,YAAY;IACZG;EACJ,CAAC;EAED,oBACIT,KAAA,CAAAY,aAAA,CAACV,qBAAqB,CAACW,QAAQ;IAACF,KAAK,EAAEA;EAAM,GAAEJ,QAAyC,CAAC;AAEjG,CAAC;AAEDF,sBAAsB,CAACS,WAAW,GAAG,wBAAwB","ignoreList":[]}