@stackbit/cms-core 1.0.18-develop.1 → 1.0.18-feature-clac.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.
@@ -3,40 +3,33 @@ import _ from 'lodash';
3
3
  import { ContentStoreTypes } from '../';
4
4
  import { STACKBIT_PRESET_MODEL_NAME } from '../consts';
5
5
  import { getContentSourceDataByIdOrThrow, getContentSourceId } from '../content-store-utils';
6
- import { mapCSIAssetsToStoreAssets, mapCSIDocumentsToStoreDocuments } from './csi-to-store-docs-converter';
6
+ import { mapCSIAssetsToStoreAssets } from './csi-to-store-docs-converter';
7
7
  import { getAllModelsFromCSIDocument } from './document-utils';
8
+ import { DocumentPermissions } from '@stackbit/types';
8
9
 
9
10
  export const getFilteredDocumentsForUser = ({
10
11
  user,
11
12
  documents,
12
- filterModel,
13
- filterDocument,
13
+ permissionsForModel,
14
+ permissionsForDocument,
14
15
  contentSourceDataById,
15
- assetSources,
16
16
  createConfigDelegate,
17
- customActionRunStateMap,
18
17
  logger
19
18
  }: {
20
19
  user?: ContentStoreTypes.User;
21
- filterModel: CSITypes.StackbitConfig['filterModel'];
22
- filterDocument: CSITypes.StackbitConfig['filterDocument'];
20
+ permissionsForModel: CSITypes.StackbitConfig['permissionsForModel'];
21
+ permissionsForDocument: CSITypes.StackbitConfig['permissionsForDocument'];
23
22
  documents: ContentStoreTypes.Document[];
24
23
  contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
25
- assetSources: CSITypes.AssetSource[];
26
24
  createConfigDelegate: () => CSITypes.ConfigDelegate;
27
- customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
28
25
  logger: CSITypes.Logger;
29
26
  }): ContentStoreTypes.Document[] => {
30
- if (!user || (!filterDocument && !filterModel)) {
27
+ if (!user) {
31
28
  return documents;
32
29
  }
33
30
 
34
31
  const documentsBySourceId = _.groupBy(documents, (object) => getContentSourceId(object.srcType, object.srcProjectId));
35
-
36
- const transformedCsiDocuments: CSITypes.DocumentWithSource[] = [];
37
-
38
32
  const resultDocuments: ContentStoreTypes.Document[] = [];
39
-
40
33
  const configDelegate = createConfigDelegate();
41
34
 
42
35
  for (const [contentSourceId, contentSourceDocuments] of Object.entries(documentsBySourceId)) {
@@ -56,7 +49,7 @@ export const getFilteredDocumentsForUser = ({
56
49
  name: modelName,
57
50
  contentSourceData,
58
51
  configDelegate,
59
- filterModel
52
+ permissionsForModel
60
53
  });
61
54
  filteredModelsMap[modelName] = filteredModel;
62
55
  }
@@ -67,55 +60,25 @@ export const getFilteredDocumentsForUser = ({
67
60
  `Can't find model with name '${document.srcModelName}' for object with id '${document.srcObjectId}' in content source '${contentSourceId}'`
68
61
  );
69
62
  }
70
- if (documentModel.hidden) {
71
- // model is hidden - return csiDocument right away as hidden
72
- resultDocuments.push({
73
- ...document,
74
- hidden: true
75
- });
76
- return;
77
- }
78
-
79
- if (!filterDocument) {
80
- // no filter function is defined, but the model is not hidden - just add this document as is
81
- resultDocuments.push(document);
82
- return;
83
- }
84
-
85
- const csiDocWithSource: CSITypes.DocumentWithSource = {
86
- ..._.cloneDeep(csiDoc),
87
- srcType: contentSourceData.srcType,
88
- srcProjectId: contentSourceData.srcProjectId
89
- };
90
- const shouldIncludeDoc = filterDocument({
91
- ...configDelegate,
92
- document: csiDocWithSource,
93
- userContext: user
63
+ const docPermissions = csiDoc.permissions ?? (documentModel.permissions as DocumentPermissions | undefined);
64
+ const permissions =
65
+ permissionsForDocument?.({
66
+ ...configDelegate,
67
+ document: {
68
+ ...csiDoc,
69
+ permissions: docPermissions,
70
+ srcType: contentSourceData.srcType,
71
+ srcProjectId: contentSourceData.srcProjectId
72
+ },
73
+ userContext: user
74
+ }) ?? docPermissions;
75
+ resultDocuments.push({
76
+ ...document,
77
+ permissions,
78
+ hidden: documentModel.hidden || document.hidden || permissions?.canView === false
94
79
  });
95
- if (typeof shouldIncludeDoc === 'undefined') {
96
- transformedCsiDocuments.push(csiDocWithSource);
97
- } else {
98
- transformedCsiDocuments.push({
99
- ...csiDocWithSource,
100
- hidden: !shouldIncludeDoc
101
- });
102
- }
80
+ return;
103
81
  });
104
-
105
- if (transformedCsiDocuments.length) {
106
- const csResultDocuments = mapCSIDocumentsToStoreDocuments({
107
- csiDocuments: transformedCsiDocuments,
108
- contentSourceInstance: contentSourceData.instance,
109
- modelMap: filteredModelsMap,
110
- defaultLocaleCode: contentSourceData.defaultLocaleCode,
111
- assetSources,
112
- customActionRunStateMap,
113
- createConfigDelegate,
114
- logger
115
- });
116
-
117
- resultDocuments.push(...(csResultDocuments ?? []));
118
- }
119
82
  }
120
83
 
121
84
  return resultDocuments;
@@ -191,12 +154,12 @@ export const getContentSourceFilteredModelsForUser = ({
191
154
  user,
192
155
  configDelegate,
193
156
  contentSourceData,
194
- filterModel
157
+ permissionsForModel
195
158
  }: {
196
159
  user?: ContentStoreTypes.User;
197
160
  configDelegate: CSITypes.ConfigDelegate;
198
161
  contentSourceData: ContentStoreTypes.ContentSourceData;
199
- filterModel: CSITypes.StackbitConfig['filterModel'];
162
+ permissionsForModel: CSITypes.StackbitConfig['permissionsForModel'];
200
163
  }): CSITypes.Model[] => {
201
164
  const filteredModels = contentSourceData.models.map((model) => {
202
165
  return getFilteredModelForUser({
@@ -204,7 +167,7 @@ export const getContentSourceFilteredModelsForUser = ({
204
167
  configDelegate,
205
168
  name: model.name,
206
169
  contentSourceData,
207
- filterModel
170
+ permissionsForModel
208
171
  });
209
172
  });
210
173
  const cleanModels = filteredModels.filter((model) => model.name !== STACKBIT_PRESET_MODEL_NAME);
@@ -216,19 +179,21 @@ export const getFilteredModelForUser = ({
216
179
  name,
217
180
  configDelegate,
218
181
  contentSourceData,
219
- filterModel
182
+ permissionsForModel
220
183
  }: {
221
184
  user?: ContentStoreTypes.User;
222
185
  name: string;
223
186
  configDelegate: CSITypes.ConfigDelegate;
224
187
  contentSourceData: ContentStoreTypes.ContentSourceData;
225
- filterModel: CSITypes.StackbitConfig['filterModel'];
188
+ permissionsForModel: CSITypes.StackbitConfig['permissionsForModel'];
226
189
  }): CSITypes.Model => {
227
190
  const model = contentSourceData.modelMap[name];
228
191
  if (!model) {
229
192
  throw new Error(`Model with name ${name} not found in source`);
230
193
  }
231
- if (!user || !filterModel) {
194
+
195
+ const shouldResolvePermissions = permissionsForModel || typeof model?.permissions === 'function';
196
+ if (!user || !shouldResolvePermissions) {
232
197
  return model;
233
198
  }
234
199
  const modelWithSource = {
@@ -236,12 +201,21 @@ export const getFilteredModelForUser = ({
236
201
  srcType: contentSourceData.srcType,
237
202
  srcProjectId: contentSourceData.srcProjectId
238
203
  };
239
- const shouldIncludeModel = filterModel({ ...configDelegate, model: modelWithSource, userContext: user });
240
- if (typeof shouldIncludeModel === 'undefined') {
241
- return model;
242
- }
204
+
205
+ const permissionsResult =
206
+ typeof model.permissions === 'function' ? model.permissions?.({ ...configDelegate, model: modelWithSource, userContext: user }) : model.permissions;
207
+ const permissionsHookResult =
208
+ permissionsForModel?.({
209
+ ...configDelegate,
210
+ model: { ...modelWithSource, permissions: permissionsResult },
211
+ userContext: user
212
+ }) ?? permissionsResult;
213
+ const permissions = _.isEmpty(permissionsHookResult) ? undefined : permissionsHookResult;
214
+
215
+ const shouldHideModel = permissions?.canView === false;
243
216
  return {
244
217
  ...model,
245
- hidden: !shouldIncludeModel
218
+ permissions,
219
+ hidden: shouldHideModel
246
220
  };
247
221
  };
@@ -1,3 +0,0 @@
1
- import * as CSITypes from '@stackbit/types';
2
- export declare function convertModels(models: Map<string, any>): (CSITypes.ObjectModel<unknown> | CSITypes.DataModel<unknown>)[];
3
- //# sourceMappingURL=model-converter.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model-converter.d.mts","sourceRoot":"","sources":["../../src/connector/model-converter.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAE5C,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,mEAYrD"}
@@ -1,138 +0,0 @@
1
- export function convertModels(models) {
2
- const createModels = [];
3
- models.forEach((model) => {
4
- if (model.getTypeName() === `Image`) {
5
- return;
6
- }
7
- const createModel = convertModel(model, models);
8
- if (createModel) {
9
- createModels.push(createModel);
10
- }
11
- });
12
- return createModels;
13
- }
14
- function convertModel(model, models) {
15
- let fieldGroups = model.fieldGroups;
16
- if (model.devOnlyFieldGroup) {
17
- fieldGroups || (fieldGroups = []);
18
- fieldGroups.push(model.devOnlyFieldGroup);
19
- }
20
- // Create doesn't have named union types
21
- if (model.isUnionType) {
22
- return false;
23
- }
24
- const name = model.originalName || model.typeName;
25
- const csiModel = {
26
- name: name,
27
- label: model.label || model.name,
28
- type: model.isObjectType ? `object` : `data`,
29
- fieldGroups,
30
- fields: sdkFieldsToStackbitFields(model.fields, models)
31
- };
32
- return csiModel;
33
- }
34
- function sdkFieldsToStackbitFields(fields, models) {
35
- return fields.map((field) => {
36
- const definedTypename = field.type;
37
- const fieldModel = models.get(definedTypename);
38
- const typename = fieldModel?.originalName || definedTypename;
39
- const isObject = fieldModel?.isObjectType;
40
- const scalarTypename = isObject
41
- ? `object`
42
- : {
43
- // create only has a number field
44
- float: 'number',
45
- int: 'number'
46
- }[typename.toLowerCase()] ||
47
- // all other scalar types are supported as lowercase typenames
48
- typename.toLowerCase();
49
- const isImage = typename === `Image`;
50
- const isReference = !isImage && fieldModel?.isNodeType;
51
- const isUnion = fieldModel?.isUnionType;
52
- const firstUnionType = isUnion && fieldModel?.compositeTypes && models.get(fieldModel.compositeTypes[0]);
53
- const isObjectUnion = firstUnionType && firstUnionType.isObjectType;
54
- const isReferenceUnion = firstUnionType && firstUnionType.isNodeType;
55
- const type = (() => {
56
- if ( /*isObject || */isObjectUnion) {
57
- return `model`;
58
- }
59
- if (isReference || isReferenceUnion) {
60
- return `reference`;
61
- }
62
- if (isUnion) {
63
- // throw new ModelError(`Unhandled union type for model ${typename}. This is a bug in the Netlify SDK.`);
64
- }
65
- if (isImage) {
66
- return `image`;
67
- }
68
- return scalarTypename;
69
- })();
70
- const stackbitField = {
71
- type,
72
- name: field.name
73
- };
74
- if (typename.toLowerCase() === `float`) {
75
- stackbitField.subtype = `float`;
76
- }
77
- //TODO
78
- if (isObject) {
79
- stackbitField.fields = fieldModel.sdkFieldsToStackbitFields();
80
- }
81
- // if (isObject) {
82
- // (stackbitField as CSITypes.FieldModelProps).models = [typename];
83
- // }
84
- // if (isObjectUnion) {
85
- // (stackbitField as CSITypes.FieldModelProps).models = fieldModel.compositeTypes.map((ct: any) => {
86
- // const fullType = models.get(ct);
87
- // return fullType!.getOriginalName();
88
- // });
89
- // }
90
- // any field names starting with _ are internal mandatory fields.
91
- // they shouldn't be set as required in the Create UI as content admins
92
- // don't need to set these fields, connector authors do.
93
- if (`required` in field && !field.name.startsWith(`_`)) {
94
- stackbitField.required = field.required;
95
- }
96
- if (`label` in field) {
97
- stackbitField.label = field.label;
98
- }
99
- if (`hidden` in field) {
100
- stackbitField.hidden = field.hidden;
101
- }
102
- if (`readOnly` in field) {
103
- stackbitField.readOnly = field.readOnly;
104
- }
105
- if (`localized` in field) {
106
- stackbitField.localized = field.localized;
107
- }
108
- if (`defaultValue` in field) {
109
- stackbitField.default = field.defaultValue;
110
- }
111
- if (`group` in field) {
112
- stackbitField.group = field.group;
113
- }
114
- if (isUnion) {
115
- stackbitField.models = (fieldModel.compositeTypes || []).map((ct) => {
116
- const fullType = models.get(ct);
117
- return fullType.getOriginalName();
118
- });
119
- }
120
- else if (isReference) {
121
- stackbitField.models = [fieldModel.getOriginalName()];
122
- }
123
- if (field.list) {
124
- const { name, required, hidden, ...items } = stackbitField;
125
- return {
126
- name,
127
- required,
128
- hidden,
129
- type: `list`,
130
- items
131
- };
132
- }
133
- else {
134
- return stackbitField;
135
- }
136
- });
137
- }
138
- //# sourceMappingURL=model-converter.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"model-converter.mjs","sourceRoot":"","sources":["../../src/connector/model-converter.mts"],"names":[],"mappings":"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"}