Description
Describe the Bug
Creating a user via curl and REST API with a few fields defined creates an empty user.
To Reproduce
Create the user via curl:
$ curl -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{ "email": "another@example.com", "first_name":"hello" }'
{"data":{"id":"3c8d7d56-ba17-49cb-a09e-2adf64c42587","first_name":null,"last_name":null,"email":null,"password":null,"location":null,"title":null,"description":null,"tags":null,"avatar":null,"language":null,"tfa_secret":null,"status":"active","role":null,"token":null,"last_access":null,"last_page":null,"provider":"default","external_identifier":null,"auth_data":null,"email_notifications":true,"appearance":null,"theme_dark":null,"theme_light":null,"theme_light_overrides":null,"theme_dark_overrides":null,"policies":[]}}
The token used belongs to an Admin user
-> the user is created, but both email and first_name fields are ignored during creation (the response includes "first_name":null,"email":null,
, which is incorrect.)
-> using Directus app/admin access, we can see the user has been created, but all fields are empty too (this is coherent with the POST JSON response)
Note: I'm running a docker image derived from Directus v11.0.2, containing curl binary. All curl calls are done from inside this custom docker container (no nginx or other RP in between).
If I perform the same curl call again, I have exactly the same behavior, and another empty user is created.
Same behavior again with an "empty json body": curl -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{}'
.
After further investigations, I found the cause: my curl cause does not have Content-Type: application/json
defined. Using curl -v
, I can see curl defaults to Content-Type: application/x-www-form-urlencoded
, which I guess Directus does not understand, then it reads the request body as "empty string" no matter what I send.
As soon as I add -H 'Content-Type: application/json'
curl's option, the user is created with the given fields correctly set:
$ curl -H 'Content-Type: application/json' -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{ "email": "hello@example.com", "first_name":"hello" }'
{"data":{"id":"e0bf25b6-f6b9-4619-a4eb-4ecf8592f993","first_name":"hello","last_name":null,"email":"hello@example.com","password":null,"location":null,"title":null,"description":null,"tags":null,"avatar":null,"language":null,"tfa_secret":null,"status":"active","role":null,"token":null,"last_access":null,"last_page":null,"provider":"default","external_identifier":null,"auth_data":null,"email_notifications":true,"appearance":null,"theme_dark":null,"theme_light":null,"theme_light_overrides":null,"theme_dark_overrides":null,"policies":[]}}
If I retry, I now get an expected error:
$ curl -H 'Content-Type: application/json' -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{ "email": "hello@example.com", "first_name":"hello" }'
{"errors":[{"message":"Value for field \"email\" in collection \"directus_users\" has to be unique.","extensions":{"collection":"directus_users","field":"email","code":"RECORD_NOT_UNIQUE"}}]}
Still, I can call multiple times with empty JSON body:
$ curl -H 'Content-Type: application/json' -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{}'
{"data":{"id":"4a190eca-aab5-4581-989e-43cd8b971ef5","first_name":null,"last_name":null,"email":null,"password":null,"location":null,"title":null,"description":null,"tags":null,"avatar":null,"language":null,"tfa_secret":null,"status":"active","role":null,"token":null,"last_access":null,"last_page":null,"provider":"default","external_identifier":null,"auth_data":null,"email_notifications":true,"appearance":null,"theme_dark":null,"theme_light":null,"theme_light_overrides":null,"theme_dark_overrides":null,"policies":[]}}
$ curl -H 'Content-Type: application/json' -X POST -H 'Authorization: Bearer admin-token' "http://127.0.0.1:8055/users" -d '{}'
{"data":{"id":"5637b9a7-9a55-4a6e-af7d-964122788e82","first_name":null,"last_name":null,"email":null,"password":null,"location":null,"title":null,"description":null,"tags":null,"avatar":null,"language":null,"tfa_secret":null,"status":"active","role":null,"token":null,"last_access":null,"last_page":null,"provider":"default","external_identifier":null,"auth_data":null,"email_notifications":true,"appearance":null,"theme_dark":null,"theme_light":null,"theme_light_overrides":null,"theme_dark_overrides":null,"policies":[]}}/
To recap, in my comprehension, there are 2 issues:
- Directus REST API should reject requests that does not have a valid Content-Type header (valid = a value Directus can handle correctly). Because according to the docs,
The API uses JSON for input and output
, andapplication/x-www-form-urlencoded
is not JSON.
I also tried with
'Content-Type: application/whatever'
and with noContent-Type
header at all, in both case an empty user is created
- empty body should not be allowed in the POST payload. Even if all users fields are optionnals, it should detect empty payload and rejects with an error like "no payload found".
I didn't test other REST API endpoints, but my guess is the behavior would be the same for endpoints where all fields are optionals (some POST, probably all PATCH). This may be highly mistaken because:
- you can create empty items in some collections
- you may receive a 200 OK after a PATCH, you think the update has been done, but no update has been performed. So one would have to check the HTTP Code 200 + the JSON response to ensure all required update has been done
Last but not least: This also may explain the behavior reported in issue directus/directus#22826
Directus Version
v11.0.2
Hosting Strategy
Self-Hosted (Docker Image)
Database
sqlite