Update category picture (via image upload) API not working
-
@pitaj No that didn't work either. I even tried escaping, quoting, single quoting the brackets. Face it, this is a bug in the API, the required field "files" is not in the code or isn't enabled somewhere else. The error is 500 Server Error. No amount of curl command-fu is going to resolve this.
What is the next step, do I need to push this over to a Git issue or something?
-
I'm pretty sure this same API is used when you upload an image through the UI.
@julian can you take a look?
-
@baris adding log output produces zero additional data, I just see the error:
2021-10-22T22:58:44.720Z [4567/19620] - error: /api/admin/category/uploadpicture Error: [[error:invalid-files]] at validateFiles (/opt/nodebb/src/middleware/index.js:112:15) at Layer.handle [as handle_request] (/opt/nodebb/node_modules/express/lib/router/layer.js:95:5) at next (/opt/nodebb/node_modules/express/lib/router/route.js:137:13) at Form.<anonymous> (/opt/nodebb/node_modules/connect-multiparty/index.js:114:7) at Form.emit (events.js:326:22) at /opt/nodebb/node_modules/multiparty/index.js:610:12 at processTicksAndRejections (internal/process/task_queues.js:79:11)
I work with API's of all flavors for my job. This sincerely looks like "files" does not exist in the API. Is it possible that this function was just not enabled, or otherwise overlooked? Server error 500's usually means bad code. I'm just not familiar enough with NodeBB to debug this myself.
-
This seems to work for me on windows.
$ curl -H "Authorization: Bearer ...." -XPOST -F cid=2 -F "files[]=@c:\ideas.png" http://127.0.0.1:4567/api/admin/category/uploadpicture Forbidden
I got a forbidden error due to missing csrf token but the file was visible on the server logs.
{ files: [ { fieldName: 'files[]', originalFilename: 'ideas.png', path: 'C:\\Users\\Baris\\AppData\\Local\\Temp\\BnugKrdsfzdSP4rlETtcLt9t.png', headers: [Object], size: 59289, name: 'ideas.png', type: 'image/png' } ] }
Did you try using
"files[]=@c:\ideas.png"
? -
@baris We did not try that way, we tried files[0]=
Now I'm getting 403 Forbidden, with invalid csrf token in the logs.
2021-10-22T23:54:52.993Z [4567/19620] - error: /api/admin/category/uploadpicture invalid csrf token
How do I get around the invalid token?
-
Here is the verbose output from my macbook:
Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 192.168.10.65... * TCP_NODELAY set * Connected to pubdump.unfufadoo.net (192.168.10.65) port 4567 (#0) > POST /api/admin/category/uploadpicture HTTP/1.1 > Host: pubdump.unfufadoo.net:4567 > User-Agent: curl/7.64.1 > Accept: */* > Authorization: Bearer e3642513-175a-4650-ae39-622505ce32ba > Content-Length: 7450 > Content-Type: multipart/form-data; boundary=------------------------23a77408539631fe > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 403 Forbidden < X-DNS-Prefetch-Control: off < Expect-CT: max-age=0 < X-Frame-Options: SAMEORIGIN < X-Download-Options: noopen < X-Content-Type-Options: nosniff < X-Permitted-Cross-Domain-Policies: none < X-XSS-Protection: 0 < Referrer-Policy: strict-origin-when-cross-origin < X-Powered-By: NodeBB < Content-Security-Policy: frame-ancestors 'self' < Set-Cookie: _csrf=KEEYRk8-aMRzJbUywg3dSE5C; Path=/ < Set-Cookie: express.sid=s%3AAZCyzQs6kMVtHBfIxhfjHyTNarERnXAx.IXyYI8wP1w3cJjJkcreNjgGJTVJGP6UoI0FXRTJQZso; Path=/; Expires=Sat, 06 Nov 2021 00:09:16 GMT; HttpOnly; SameSite=Lax < Content-Type: text/plain; charset=utf-8 < Content-Length: 9 < ETag: W/"9-PatfYBLj4Um1qTm5zrukoLhNyPU" < Date: Sat, 23 Oct 2021 00:09:16 GMT < Connection: keep-alive < Keep-Alive: timeout=5 < * Connection #0 to host pubdump.unfufadoo.net left intact Forbidden* Closing connection 0
I see the message "We are completely uploaded and fine" in the above. But ultimately am getting the invalid token error over and over.
-
I think you have to first load a regular route and get a csrf token and then use that in your POST call. I am not sure how to do that in curl. Our tests do it using request https://github.com/NodeBB/NodeBB/blob/master/test/helpers/index.js#L14 and then storing the cookies then we use it to make POST requests.
-
This worked for me give it a try
# get csrf token and save cookies curl http://127.0.0.1:4567/api/config -c cookies.txt -s | grep csrf #this will print something like "csrf_token": "bHqyDEde-Y_zLYuitkD4uc5Cd7-0mYF1m5GU",
Copy the value of the csrf_token and make the upload also use
cookies.txt
with-b cookies.txt
curl -H "Authorization: Bearer da21bf5f-6924-4e5d-9a82-92191e6f2240" -XPOST \ -F params="{\"cid\":\"2\"}" \ -F "files[]=@c:\ideas.png" \ -F "_csrf=bHqyDEde-Y_zLYuitkD4uc5Cd7-0mYF1m5GU" \ -b cookies.txt \ http://127.0.0.1:4567/api/admin/category/uploadpicture
Should get this output
[ { "name": "ideas.png", "url": "/assets/uploads/category/category-2.png" } ]
-
@baris Thank-you, found it, it is a PUT on the write API. First go, I got the syntax mostly correct, I got a 200 OK message, but the Response:backgroundImage key was empty.
I will poke at this more after dinner, but I think we can call this one solved, since it is just a matter of figuring out the right syntax at this point.
-
@baris Using the below site, reminding me of just how powerful Chrome Developers tools are, I was able to Copy As Curl the specific PUT command.
Then using the same command and just changing the CID, I confirmed the same command works for all of them.
This is what ended up working, it includes all the recorded headers, of which some will be removed as not necessary:
curl 'http://pubdump.unfufadoo.net:4567/api/v3/categories/80' \ -X 'PUT' \ -H 'Connection: keep-alive' \ -H 'Accept: */*' \ -H 'DNT: 1' \ -H 'x-csrf-token: H5FMJEaY-CthHWM_2Unzf7DtoPeryGq_JejE' \ -H 'X-Requested-With: XMLHttpRequest' \ -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' \ -H 'Content-Type: application/json; charset=UTF-8' \ -H 'Origin: http://pubdump.unfufadoo.net:4567' \ -H 'Referer: http://pubdump.unfufadoo.net:4567/admin/manage/categories/80' \ -H 'Accept-Language: en-US,en;q=0.9,zh;q=0.8,zh-CN;q=0.7,zh-TW;q=0.6,ja;q=0.5,ko;q=0.4,th;q=0.3' \ -H 'Cookie: _csrf=27ygKMdG0c0EyiVsJKAkKpId; express.sid=s%3AdODaXfUpLz7NTFsijWLq0d2rPUhH1Ki4.qkyxWOaxlBy%2BLDRpTYbhWS9QkD9IJE%2FRTN1vIhp7yV4' \ -H 'sec-gpc: 1' \ --data '{"backgroundImage":"/assets/uploads/category/category-84.jpg"}' \ --compressed \ --insecure
Then using the cURL convert site, was able to save as javascript and modify to our needs so that we could loop through all categories.
Jeff
-