Getting and Setting metadata without groupfolder leads to unpredictable results
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 25
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
How to use GitHub
- Please use the 👍 reaction to show that you are affected by the same issue.
- Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
- Subscribe to receive notifications on status change and new comments.
According to the documentation here is it possible to get and set the metadata for a file without having to specify the group folder.
My assumption was that it would read and write the metadata for the group folder, in which the file is located at that time.
This is not the case and the core issue: I cannot tell where the data comes from, if it returns non-empty metadata in the first place, nor which group folder it writes to.
Reproducing this error is difficult too, because we have 2 Nextcloud instances which both have Metavox installed and they don't even behave the same.
In our prod instance, I can read and write metadata of a file, and I get back what I just wrote.
But Nextcloud doesn't reflect this data, because Metavox decided to read and write from a different group folder that exists, but does not hold said file.
In our dev instance I can write the metadata, but I get nothing back when reading it. It's just an empty 200 response for a file that has supposedly not a single metadata field attached to it.
The written data was not lost either, here it actually ended up in the correct group folder, but it's apparently reading from a non-existing one.
I assume this because there is only 2 group folders and both return metadata for the file when read via the endpoint that also requires the group folder id. The only empty results come back when I read for group folders that don't exist.
They still return a 200 and completely hide the fact that I just asked for metadata of a folder that doesn't exist.
On top of this: the bulk reading endpoint returns all group folders metadata without specifying from which group folder it came.
This then allows for results such as this
<?xml version="1.0"?>
<ocs>
<meta>
<status>ok</status>
<statuscode>200</statuscode>
<message>OK</message>
</meta>
<data>
<element>
<element>
<id>15</id>
<field_name>file_gf_mark_for_deletion</field_name>
<field_label>Mark for Deletion</field_label>
<field_type>text</field_type>
<field_description>Enter the deletion reason which will be reviewed.</field_description>
<field_options/>
<is_required></is_required>
<value>4</value>
</element>
<element>
<id>15</id>
<field_name>file_gf_mark_for_deletion</field_name>
<field_label>Mark for Deletion</field_label>
<field_type>text</field_type>
<field_description>Enter the deletion reason which will be reviewed.</field_description>
<field_options/>
<is_required></is_required>
<value>3</value>
</element>
<element>
<id>15</id>
<field_name>file_gf_mark_for_deletion</field_name>
<field_label>Mark for Deletion</field_label>
<field_type>text</field_type>
<field_description>Enter the deletion reason which will be reviewed.</field_description>
<field_options/>
<is_required></is_required>
<value>1</value>
</element>
<element>
<id>15</id>
<field_name>file_gf_mark_for_deletion</field_name>
<field_label>Mark for Deletion</field_label>
<field_type>text</field_type>
<field_description>Enter the deletion reason which will be reviewed.</field_description>
<field_options/>
<is_required></is_required>
<value>yup</value>
</element>
<element>
<id>15</id>
<field_name>file_gf_mark_for_deletion</field_name>
<field_label>Mark for Deletion</field_label>
<field_type>text</field_type>
<field_description>Enter the deletion reason which will be reviewed.</field_description>
<field_options/>
<is_required></is_required>
<value>2</value>
</element>
</element>
</data>
</ocs>
To produce this, I used the endpoint that also requires the group folder id and wrote said id into the metadata field. This includes the folders 3 and 4 which don't even exist. I don't even know where the 5th value comes from, which perfectly illustrates the problem.
Further more, when I read this file's metadata for group folder 1, I don't even get the value shown in the bulk response back, because that field is not assigned to group folder 1.
Instead I only get the fields that are actually assigned to that folder.
All of this makes the bulk reading endpoint and the endpoints for reading and writing metadata that do not require a group folder id effectively useless.
Expected behaviour
The endpoints that don't require the group folder id should read from and write into the group folder in which the file is currently located, just how Nextcloud's ui does it.
The bulk endpoint should either only return the metadata for the group folder a file is located in at the time, or it should specify which group folder a mixed return of metadata belongs to.
Maybe even have an argument for returning all or just current.
When writing metadata for a folder that does not exist yet, it should return an error instead of writing the data "for later".
Actual behaviour
As described above.
Currently the only way to correctly get the metadata for any file is to find out in which group folder it currently sits, find that group folder's id and then retrieve the correct metadata from that group folder.
Server configuration
Web server: NC-AIO Apache
Database: PostgreSQL 18.4 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
PHP version: 8.3.31
Nextcloud version: AIO Nextcloud Hub 26 Spring (34.0.1)
List of activated apps
- activity: 7.0.0
- admin_audit: 1.24.0
- app_api: 34.0.0
- appstore: 1.0.0
- bruteforcesettings: 7.0.0
- calendar: 6.5.1
- circles: 34.0.0
- cloud_federation_api: 1.18.0
- comments: 1.24.0
- contacts: 8.7.3
- contactsinteraction: 1.15.0
- dashboard: 7.14.0
- dav: 1.39.0
- deck: 1.18.2
- federatedfilesharing: 1.24.0
- federation: 1.24.0
- files: 2.6.0
- files_antivirus: 6.3.0
- files_downloadlimit: 5.2.0-dev.0
- files_lock: 34.0.0
- files_pdfviewer: 7.0.0-dev.0
- files_reminders: 1.7.0
- files_sharing: 1.26.0
- files_trashbin: 1.24.0
- files_versions: 1.27.0
- firstrunwizard: 7.0.0-dev.0
- groupfolders: 22.0.3
- integration_windmill: 1.1.0
- intravox: 1.8.4
- logreader: 7.0.0
- lookup_server_connector: 1.22.0
- metavox: 2.2.0
- nextcloud-aio: 0.8.0
- nextcloud_announcements: 6.0.0
- notes: 6.0.1
- notifications: 7.0.0-dev.1
- notify_push: 1.3.3
- oauth2: 1.22.0
- office: 1.0.0
- password_policy: 6.0.0-dev.0
- photos: 7.0.0
- privacy: 6.0.0-dev.1
- profile: 1.3.0
- provisioning_api: 1.24.0
- recommendations: 7.0.0
- related_resources: 5.0.0-dev.0
- richdocuments: 11.0.1
- serverinfo: 6.0.0
- settings: 1.17.0
- sharebymail: 1.24.0
- sociallogin: 6.5.2
- support: 6.0.0
- survey_client: 6.0.0-dev.0
- systemtags: 1.24.0
- tables: 2.2.0
- tasks: 0.18.1
- text: 8.0.0
- theming: 2.9.0
- twofactor_backupcodes: 1.23.0
- twofactor_totp: 16.0.0
- updatenotification: 1.24.0
- user_status: 1.14.0
- viewer: 7.0.0-dev.0
- vwork: 1.0.0
- weather_status: 1.14.0
- webhook_listeners: 1.6.0
- workflowengine: 2.16.0
Nextcloud configuration
{
"system": {
"one-click-instance": true,
"one-click-instance.user-limit": 100,
"update_channel": "stable",
"memcache.local": "\\OC\\Memcache\\APCu",
"apps_paths": [
{
"path": "\/var\/www\/html\/apps",
"url": "\/apps",
"writable": false
},
{
"path": "\/var\/www\/html\/custom_apps",
"url": "\/custom_apps",
"writable": true
}
],
"check_data_directory_permissions": false,
"memcache.distributed": "\\OC\\Memcache\\Redis",
"memcache.locking": "\\OC\\Memcache\\Redis",
"redis": {
"host": "***REMOVED SENSITIVE VALUE***",
"timeout": 3,
"read_timeout": 10,
"password": "***REMOVED SENSITIVE VALUE***",
"port": 6379
},
"overwritehost": "company.com",
"overwriteprotocol": "https",
"serverid": 445,
"passwordsalt": "***REMOVED SENSITIVE VALUE***",
"secret": "***REMOVED SENSITIVE VALUE***",
"trusted_domains": [
"localhost",
"company.com"
],
"datadirectory": "***REMOVED SENSITIVE VALUE***",
"dbtype": "pgsql",
"version": "34.0.1.2",
"overwrite.cli.url": "https:\/\/company.com\/",
"instanceid": "***REMOVED SENSITIVE VALUE***",
"dbname": "***REMOVED SENSITIVE VALUE***",
"dbhost": "***REMOVED SENSITIVE VALUE***",
"dbtableprefix": "oc_",
"dbuser": "***REMOVED SENSITIVE VALUE***",
"dbpassword": "***REMOVED SENSITIVE VALUE***",
"installed": true,
"maintenance": false,
"updatechecker": true,
"updatedirectory": "\/nc-updater",
"loglevel": 2,
"app_install_overwrite": [
"nextcloud-aio"
],
"log_type": "file",
"log_type_audit": "file",
"logfile": "\/var\/www\/html\/data\/nextcloud.log",
"logfile_audit": "\/var\/www\/html\/data\/audit.log",
"log_rotate_size": 10485760,
"log.condition": {
"apps": [
"admin_audit"
]
},
"preview_max_x": 2048,
"preview_max_y": 2048,
"jpeg_quality": 60,
"enabledPreviewProviders": {
"1": "OC\\Preview\\Image",
"2": "OC\\Preview\\MarkDown",
"3": "OC\\Preview\\MP3",
"4": "OC\\Preview\\TXT",
"5": "OC\\Preview\\OpenDocument",
"6": "OC\\Preview\\Movie",
"7": "OC\\Preview\\Krita",
"0": "OC\\Preview\\Imaginary",
"23": "OC\\Preview\\ImaginaryPDF"
},
"enable_previews": true,
"upgrade.disable-web": true,
"mail_smtpmode": "smtp",
"trashbin_retention_obligation": "auto, 30",
"versions_retention_obligation": "auto, 30",
"activity_expire_days": 30,
"simpleSignUpLink.shown": false,
"share_folder": "\/Shared",
"one-click-instance.link": "https:\/\/nextcloud.com\/all-in-one\/",
"upgrade.cli-upgrade-link": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/2726",
"maintenance_window_start": 100,
"allow_local_remote_servers": true,
"davstorage.request_timeout": 3600,
"documentation_url.server_logs": "https:\/\/github.com\/nextcloud\/all-in-one\/discussions\/5425",
"htaccess.RewriteBase": "\/",
"dbpersistent": false,
"auth.bruteforce.protection.enabled": true,
"ratelimit.protection.enabled": true,
"files_external_allow_create_new_local": false,
"trusted_proxies": "***REMOVED SENSITIVE VALUE***",
"preview_imaginary_url": "***REMOVED SENSITIVE VALUE***",
"preview_imaginary_key": "***REMOVED SENSITIVE VALUE***",
"mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
"mail_smtpname": "***REMOVED SENSITIVE VALUE***",
"mail_domain": "***REMOVED SENSITIVE VALUE***",
"mail_from_address": "***REMOVED SENSITIVE VALUE***",
"mail_smtphost": "***REMOVED SENSITIVE VALUE***",
"mail_smtpauth": true,
"mail_smtpport": "465",
"mail_sendmailmode": "smtp",
"mail_smtpstreamoptions": {
"ssl": {
"allow_self_signed": false,
"verify_peer": true,
"verify_peer_name": true
}
},
"DOMAIN": "company.com",
"AIO_VERSION": "v13.3.1"
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with docs/architecture/api-reference.md#file-metadata and compare the group-folder and folder-independent metadata endpoints described there. Reproduce reads and writes with existing and nonexistent group folder IDs, then define behavior for current-folder access, bulk responses, and invalid IDs. Done means endpoint responses identify or consistently use the relevant group folder and reject nonexistent targets.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100