notes
notes copied to clipboard
Ignoring `readonly` attribute leads to `500` when origin is another instance
Steps to reproduce
- Create a folder with a text file on Nextcloud instance A
- Share this folder without write permissions to a user on Nextcloud instance B (via federated sharing)
- Move the folder in Nextcloud instance B into your
/Notesfolder - Try editing and saving it on Nextcloud instance B
Expected behaviour
Http 403 should be returned
Actual behaviour
Http 500 will be returned
Screenshots

Server
Please complete the following information.
- Notes app version: 4.3.1
- Nextcloud version: 23.0.3
- OS:
- Web server:
- PHP version: 8.1
- Database: MySQL
Nextcloud configuration:
```
If you have access to your command line run e.g.:
sudo -u www-data php occ config:list system
from within your Nextcloud installation folder
```
Client
Please complete the following information.
- Browser (incl. version): Firefox
- OS: Debian
Log files
{
"reqId":"YkIQE-M1vxwFYekKdJU9PgAAAB0",
"level":3,
"time":"2022-03-28T19:44:23+00:00",
"remoteAddr":"2a01:c23:c1d5:a700:7801:4875:61b8:ec3b",
"user":"userB",
"app":"notes",
"method":"PUT",
"url":"/index.php/apps/notes/notes/227690",
"message":"Controller failed with GuzzleHttp\\Exception\\ClientException",
"userAgent":"Mozilla/5.0 (X11; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0",
"version":"23.0.3.2",
"exception":{
"Exception":"GuzzleHttp\\Exception\\ClientException",
"Message":"Client error: `PUT https://a.example.com/public.php/webdav/Shared%20note.md` resulted in a `403 Forbidden` response:\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<d:error xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\">\n <s:exception>Sabre\\DA (truncated...)\n",
"Code":403,
"Trace":[
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/guzzle/src/Middleware.php",
"line":69,
"function":"create",
"class":"GuzzleHttp\\Exception\\RequestException",
"type":"::"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":204,
"function":"GuzzleHttp\\{closure}",
"class":"GuzzleHttp\\Middleware",
"type":"::",
"args":[
"*** sensitive parameters replaced ***"
]
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":153,
"function":"callHandler",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"::"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/TaskQueue.php",
"line":48,
"function":"GuzzleHttp\\Promise\\{closure}",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"::",
"args":[
"*** sensitive parameters replaced ***"
]
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":248,
"function":"run",
"class":"GuzzleHttp\\Promise\\TaskQueue",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":224,
"function":"invokeWaitFn",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":269,
"function":"waitIfPending",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":226,
"function":"invokeWaitList",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/promises/src/Promise.php",
"line":62,
"function":"waitIfPending",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/guzzle/src/Client.php",
"line":187,
"function":"wait",
"class":"GuzzleHttp\\Promise\\Promise",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Http/Client/Client.php",
"line":329,
"function":"request",
"class":"GuzzleHttp\\Client",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/DAV.php",
"line":515,
"function":"put",
"class":"OC\\Http\\Client\\Client",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/DAV.php",
"line":422,
"function":"uploadFile",
"class":"OC\\Files\\Storage\\DAV",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/DAV.php",
"line":413,
"function":"writeBack",
"class":"OC\\Files\\Storage\\DAV",
"type":"->"
},
{
"function":"OC\\Files\\Storage\\{closure}",
"class":"OC\\Files\\Storage\\DAV",
"type":"->",
"args":[
"*** sensitive parameters replaced ***"
]
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/icewind/streams/src/CallbackWrapper.php",
"line":119,
"function":"call_user_func"
},
{
"function":"stream_close",
"class":"Icewind\\Streams\\CallbackWrapper",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/Common.php",
"line":209,
"function":"fclose"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/DAV.php",
"line":494,
"function":"file_put_contents",
"class":"OC\\Files\\Storage\\Common",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/Wrapper/Wrapper.php",
"line":258,
"function":"file_put_contents",
"class":"OC\\Files\\Storage\\DAV",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/Wrapper/Availability.php",
"line":274,
"function":"file_put_contents",
"class":"OC\\Files\\Storage\\Wrapper\\Wrapper",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Storage/Wrapper/Wrapper.php",
"line":258,
"function":"file_put_contents",
"class":"OC\\Files\\Storage\\Wrapper\\Availability",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/View.php",
"line":1169,
"function":"file_put_contents",
"class":"OC\\Files\\Storage\\Wrapper\\Wrapper",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/View.php",
"line":706,
"function":"basicOperation",
"class":"OC\\Files\\View",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Files/Node/File.php",
"line":71,
"function":"file_put_contents",
"class":"OC\\Files\\View",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/apps/notes/lib/Service/Note.php",
"line":171,
"function":"putContent",
"class":"OC\\Files\\Node\\File",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/apps/notes/lib/Controller/NotesController.php",
"line":226,
"function":"setContent",
"class":"OCA\\Notes\\Service\\Note",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/apps/notes/lib/Service/Util.php",
"line":28,
"function":"OCA\\Notes\\Controller\\{closure}",
"class":"OCA\\Notes\\Controller\\NotesController",
"type":"->",
"args":[
"*** sensitive parameters replaced ***"
]
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/apps/notes/lib/Controller/Helper.php",
"line":145,
"function":"retryIfLocked",
"class":"OCA\\Notes\\Service\\Util",
"type":"::"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/apps/notes/lib/Controller/NotesController.php",
"line":228,
"function":"handleErrorResponse",
"class":"OCA\\Notes\\Controller\\Helper",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/AppFramework/Http/Dispatcher.php",
"line":217,
"function":"update",
"class":"OCA\\Notes\\Controller\\NotesController",
"type":"->",
"args":[
"*** sensitive parameters replaced ***"
]
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/AppFramework/Http/Dispatcher.php",
"line":126,
"function":"executeController",
"class":"OC\\AppFramework\\Http\\Dispatcher",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/AppFramework/App.php",
"line":157,
"function":"dispatch",
"class":"OC\\AppFramework\\Http\\Dispatcher",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/private/Route/Router.php",
"line":302,
"function":"main",
"class":"OC\\AppFramework\\App",
"type":"::"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/lib/base.php",
"line":1006,
"function":"match",
"class":"OC\\Route\\Router",
"type":"->"
},
{
"file":"/var/www/vhosts/b.example.com/b.example.com/index.php",
"line":36,
"function":"handleRequest",
"class":"OC",
"type":"::"
}
],
"File":"/var/www/vhosts/b.example.com/b.example.com/3rdparty/guzzlehttp/guzzle/src/Exception/RequestException.php",
"Line":113,
"CustomMessage":"Controller failed with GuzzleHttp\\Exception\\ClientException"
},
"id":"6242101826d1c"
}
That's an interesting use case, we don't have this in our CI tests, yet. At first sight, it looks like the Nextcloud framework says, that the file is writable - although it isn't. The Notes app calls OC\Files\Node\File.isUpdateable() for checking writability - which appears to not work in this case. Otherwise the Notes app would have opened the editor in read-only mode.
I would say that's a bug in Nextcloud server, but I'll try to reproduce this for further insights.