Skip to content

Commit 25daeae

Browse files
committed
Merge branch 'stable' into feature-DATAAPI-37_support_custom_endpoints
2 parents e30bfc7 + 7476f16 commit 25daeae

File tree

9 files changed

+362
-55
lines changed

9 files changed

+362
-55
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## v3.7.1
4+
5+
* Always respect returned value from custom field renderer
6+
7+
## v3.7.0
8+
9+
* new options to skip data validation and customize the response type on inserts/updates, also 4 new interception points added
10+
311
## v3.6.0
412

513
* Added a UI to show records in the DATA API change queue per subscribed API client

README.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ Additional _optional_ annotation options at the _object_ level are:
5252
* `dataApiFilterFields`: Fields to allow as simple filters for paginated GET requests (defaults to foreign keys, boolean and enum fields)
5353
* `dataApiAllowIdInsert`: Whether or not to allow the ID field to be set during a POST operation to create a new record
5454
* `dataApiQueueRelevantFields`: Fields that are relevant to trigger a record update to be queued. If not used, then any data change will be queued. If used then only the specified fields will be examined and in case of atomic-changes for the queue only the relevant field changes will be included in the queue item. Inserts and deletes are always queued, only during updates this annotation is evaluated.
55+
* `dataApiSkipValidationOnInsert`: Whether or not to skip data validation when inserting new records (defaults to `false`)
56+
* `dataApiSkipValidationOnUpdate`: Whether or not to skip data validation when updating records (defaults to `false`)
57+
* `dataApiResponseTypeOnInsert`: Could be `record`, `idonly` or `empty` (defaults to `record`)
58+
* `dataApiResponseTypeOnUpdate`: Could be `record`, `idonly` or `empty` (defaults to `record`)
5559

5660
### Property annotations
5761

@@ -191,7 +195,7 @@ Fires before inserting data through the API. Receives the following keys in the
191195
* `insertDataArgs`: Arguments that will be passed to the `insertData()` call
192196
* `entity`: Name of the entity being operated on
193197
* `record`: The data that will be inserted (struct)
194-
198+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
195199

196200
### `postDataApiInsertData`
197201

@@ -201,7 +205,7 @@ Fires after inserting data through the API. Receives the following keys in the `
201205
* `entity`: Name of the entity being operated on
202206
* `record`: The data that will be inserted (struct)
203207
* `newId`: Newly created record ID
204-
208+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
205209

206210
### `preDataApiUpdateData`
207211

@@ -211,6 +215,7 @@ Fires before updating data through the API. Receives the following keys in the `
211215
* `entity`: Name of the entity being operated on
212216
* `recordId`: ID of the record to be updated
213217
* `data`: The data that will be inserted (struct)
218+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
214219

215220
### `postDataApiUpdateData`
216221

@@ -220,6 +225,7 @@ Fires after updating data through the API. Receives the following keys in the `i
220225
* `entity`: Name of the entity being operated on
221226
* `recordId`: ID of the record to be updated
222227
* `data`: The data that will be inserted (struct)
228+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
223229

224230
### `preDataApiDeleteData`
225231

@@ -237,6 +243,39 @@ Fires after deleting data through the API. Receives the following keys in the `i
237243
* `entity`: Name of the entity being operated on
238244
* `recordId`: ID of the record to be deleted
239245

246+
### `onDataApiUpdateRecordDataValidation`
247+
248+
Fires before starting data validation on updates. Receives the following keys in the `interceptData`:
249+
250+
* `entity`: Name of the entity being operated on
251+
* `data`: The data to be validated
252+
* `skipValidation`: Whether the whole validation should be skipped. Defaults to the API or object definition, but can be overwritte here.
253+
254+
### `onDataApiInsertRecordDataValidation`
255+
256+
Fires before starting data validation on inserts. Receives the following keys in the `interceptData`:
257+
258+
* `entity`: Name of the entity being operated on
259+
* `data`: The data to be validated
260+
* `skipValidation`: Whether the whole validation should be skipped. Defaults to the API or object definition, but can be overwritte here.
261+
262+
### `preDataApiBatchUpdateRecords`
263+
264+
Fires before batch updating multiple records. Receives the following keys in the `interceptData`:
265+
266+
* `entity`: Name of the entity being operated on
267+
* `records`: Array of record data to be batch updated
268+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
269+
270+
### `postDataApiBatchUpdateRecords`
271+
272+
Fires after multiple records have been batch updated. Receives the following keys in the `interceptData`:
273+
274+
* `entity`: Name of the entity being operated on
275+
* `records`: Array of record data to be batch updated
276+
* `responseType`: Whether the API response should be `empty`, contain the full `record` or `idonly`. Defaults to the API or object definition (or if not defined `record`), but can be overwritten here.
277+
* `updated`: Array of the full record data that was updated (or empty array in case skipRecordResponse=true was already set in `preDataApiBatchUpdateRecords`)
278+
240279
## Data Change Queue(s)
241280

242281
By default, they system enables a queue feature: `settings.features.dataApiQueue`. When enabled, API users can be subscribed, through the admin UI, to listen for data changes to all, or a number, of entities in the system.

config/Config.cfc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ component {
2727
, description = "Generic Preside REST API for external systems to interact with Preside data"
2828
, configHandler = "dataApiManager"
2929
, dataApiQueues = { default={ pageSize=1, name="", atomicChanges=false } }
30-
, dataApiDefaults = { allowIdInsert=false }
30+
, dataApiDefaults = {
31+
allowIdInsert = false
32+
, skipValidationOnInsert = false
33+
, skipValidationOnUpdate = false
34+
, responseTypeOnInsert = "record" // "empty", "idonly" or "record" (default)
35+
, responseTypeOnUpdate = "record" // "empty", "idonly" or "record" (default)
36+
}
3137
};
3238
settings.rest.apis[ "/data/v1/docs" ] = {
3339
description = "Documentation for REST APIs (no authentication required)"
@@ -57,6 +63,10 @@ component {
5763
, "postDataApiSelectData"
5864
, "preValidateUpsertData"
5965
, "postValidateUpsertData"
66+
, "onDataApiUpdateRecordDataValidation"
67+
, "onDataApiInsertRecordDataValidation"
68+
, "preDataApiBatchUpdateRecords"
69+
, "postDataApiBatchUpdateRecords"
6070
];
6171
conf.interceptorSettings.customInterceptionPoints.append( conf.settings.dataApiInterceptionPoints, true );
6272
}

handlers/rest-apis/data/v1/SingleRecord.cfc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,23 @@ component {
7070
return;
7171
}
7272

73-
7473
var updated = dataApiService.updateSingleRecord(
75-
entity = entity
76-
, recordId = recordId
77-
, data = validationData
74+
entity = entity
75+
, recordId = recordId
76+
, data = validationData
77+
, returnResponse = true
7878
);
7979

80-
if ( updated ) {
81-
get( argumentCollection=arguments );
82-
} else {
80+
if ( IsNumeric( updated ) && updated == 0 ) {
8381
restResponse.setError(
8482
errorCode = 404
8583
, title = "Not found"
8684
, message = "No [#arguments.entity#] record was found with ID [#arguments.recordId#]"
8785
);
86+
} else if ( IsStruct( updated ) || IsArray( updated ) ) { // updated and configured to either return the full record or the id only (in an array)
87+
restResponse.setData( updated );
88+
} else { // updated but configured to return an empty response
89+
restResponse.noData();
8890
}
8991
}
9092

handlers/rest-apis/data/v1/WholeEntity.cfc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ component {
8585
, data = body
8686
, ignoreMissing = false
8787
);
88+
8889
if ( IsArray( body ) ) {
8990
if ( !validationResult.validated ) {
9091
restResponse.setError(
@@ -110,7 +111,11 @@ component {
110111
, records = IsArray( body ) ? body : [ body ]
111112
);
112113

113-
restResponse.setData( created );
114+
if ( IsArray( created ) ) {
115+
restResponse.setData( created );
116+
} else {
117+
restResponse.noData();
118+
}
114119
}
115120

116121
private void function put( required string entity ) {
@@ -160,7 +165,10 @@ component {
160165
, records = body
161166
);
162167

163-
restResponse.setData( updated );
168+
if ( IsArray( updated ) ) {
169+
restResponse.setData( updated );
170+
} else {
171+
restResponse.noData();
172+
}
164173
}
165-
166174
}

i18n/dataapi.properties

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,24 @@ operation.get.by.id.params.recordId=ID of the **{1}** record that you wish to fe
8282

8383
operation.put.description=Used to batch update **{1}** records.
8484
operation.put.200.description=Array of updated **{1}** records.
85+
operation.put.200.description.idonly=Array of updated **{1}** records IDs.
86+
operation.put.200.description.empty=Empty
8587
operation.put.422.description=Data validation failure. Returned when one or more entities failed validation. No records will have been updated.
8688
operation.put.body.description=Array of **{1}** objects to update. Missing fields per item will be ignored and only fields given will be updated.
8789

8890
operation.put.by.id.description=Used to update an individual **{1}** record by ID.
8991
operation.put.by.id.200.description=Updated **{1}** record object
92+
operation.put.by.id.200.description.idonly=ID of the updated **{1}** record object
93+
operation.put.by.id.200.description.empty=Empty
9094
operation.put.by.id.404.description=No record found for the given ID
9195
operation.put.by.id.422.description=Data validation failure. Returned when one or more fields have failed validation.
9296
operation.put.by.id.params.recordId=ID of the **{1}** record that you wish to update.
9397
operation.put.by.id.body.description=**{1}** object with fields to update. Missing fields will be ignored.
9498

95-
9699
operation.post.description=Used to create **{1}** records.
97100
operation.post.200.description=Array of created **{1}** records.
101+
operation.post.200.description.idonly=Array of created **{1}** record IDs.
102+
operation.post.200.description.empty=Empty
98103
operation.post.422.description=Data validation failure. Returned when one or more entities failed validation. No records will have been created.
99104
operation.post.body.description=Array of **{1}** objects to create.
100105

0 commit comments

Comments
 (0)