I am not sure this is a bug or a feature, but using this example config
{
"name": "Account",
"base": "PersistedModel",
"strict": true,
"idInjection": false,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"id": true,
"required": true,
"type": "string",
"defaultFn": "uuid"
},
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
The id can be redefined through REST API, and the value provided in the body has precedence over the "uuid" value.
It can be easily fixed with an operation hook
const uuidV4 = require('uuid/v4');
module.exports = function(Account) {
Account.observe('before save', function(ctx, cb){
if (ctx.instance) {
ctx.instance.id = uuidV4();
} else {
ctx.data.id = uuidV4();
}
cb();
});
};
But it's rather inconsistent with the behavior of "idInjection": true where the id cannot be defined through REST api. So is this the expected behavior ?
I would say yes its consistent because your are overriding default autoinc behaviour which injects numeric ids. I do agree it is sort of clunky and that you should be able to declare uuid type as part of the model definiton. @raymondfeng Thoughts?
For future reference, please post questions at on our Google Groups forum or try asking using live chat on our Gitter. We reserve GitHub issues for features and bug reports only. See https://github.com/strongloop/loopback/wiki/Questions for more details.
Also you may consider using forceId: true if you want to prevent users from setting the generated id value manually.
Please see: https://loopback.io/doc/en/lb3/Model-definition-JSON-file.html#top-level-properties
forceId was exactly what I was looking for. Maybe it could be worth mentionning it in https://loopback.io/doc/en/lb3/Model-definition-JSON-file.html#id-properties
However, using forceId with the following config is not working, the user-defined id takes precedence.
{
"name": "Account",
"base": "PersistedModel",
"idInjection": true,
"forceId": true,
"options": {
"validateUpsert": true
},
"properties": {
"id": {
"id": true,
"type": "string",
"defaultFn": "uuid"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Request
curl -X PUT --header "Content-Type: application/json" --header "Accept: application/json" -d "{
\"id\": \"ea23de\"
}" "http://localhost:3000/api/Accounts"
Response 200
{
"id": "ea23de"
}
Looks like a bug with forceId.
In the project loopback-datasource-juggler this line, https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/datasource.js#L524, is causing forceId to be ignored:
The id property would need to have generated: true in the config for forceId to work properly.
"properties": {
"id": {
"id": true,
"type": "string",
"defaultFn": "uuid",
"generated": true
}
}
This line, https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/model-builder.js#L287, is when generated: true gets set.
I also was able to have forceId applied by setting the id property to false:
"properties": {
"id": {
"id": false,
"type": "string",
"defaultFn": "uuid"
}
}
@superkhau This issue seems still present, would you be ok to reopen ? I can write a test to confirm it
Most helpful comment
@superkhau This issue seems still present, would you be ok to reopen ? I can write a test to confirm it