#Users cannot update documents with document-level permission

43 messages · Page 1 of 1 (latest)

faint swallow
#

Hello,

I encounter a strange bug while working on a web app.
I have two collections with document-level security.
On the collection level, users can create documents, but cannot read, update or delete.
On the documents created by the user, they assign themselves read and update permissions.

When I try to update a document signed in as a user, I get a 401 error:

{
    "message": "The current user is not authorized to perform the requested action.",
    "code": 401,
    "type": "user_unauthorized",
    "version": "1.3.7"
}

Appwrite log:

[Error] Method: PATCH
[Error] URL: /v1/databases/:databaseId/collections/:collectionId/documents/:documentId
[Error] Type: Appwrite\Extend\Exception
[Error] Message: The current user is not authorized to perform the requested action.
[Error] File: /usr/src/code/app/controllers/api/databases.php
[Error] Line: 3295

I know the appwrite session cookie is valid because users can read documents where they have read permission.

The strange thing is that I added Any that can update, and users still can't update the documents.
Also, I have a third collection with the same setup (document-level security, users can create from collection, then update their documents), which is working fine.
The two collections failing have a relationship between them.

I tried from a server-side script (authentified via an API key) to update the document, which is successfull.

Any idea?

faint swallow
safe portal
#

After the upgrade did you run migrate?

faint swallow
safe portal
#

👍

#

And in the server side SDK when you fetch the document you can see that the current user has indeed update access to it?

verbal marsh
faint swallow
verbal marsh
faint swallow
#

The document

faint swallow
#

I doubled check that the user is the good one and that its current session is valid

#

I'm calling

PATCH
/v1/databases/.../collections/.../documents/...
{data: {name: "Test"}}

I also doubled check the database, collection, and document id

faint swallow
#

The error is triggered in a block that checks for !$documentSecurity, but document security is enabled on the collection

#

When getting the collection, documentSecurity is true

verbal marsh
verbal marsh
faint swallow
#

I think it's where the error is coming from, because the only collection without a relationship inside is working

faint swallow
verbal marsh
faint swallow
#

To make sure my setup is clear:

I have 2 collections: A and B.
A has a two-way relationship attribute with B.

Both A and B have document security enabled, both have only the create permission for users.

There are 2 documents, document 1 in A, document 2 in B.
There is a two-way relationship of document 1 to document 2.

Both document 1 and document 2 has read and update permissions for the user.
When the user edits one string attribute of document 1, it yields a 401.
When the user edits one string attribute of document 2, it yields a 401 as well.
When the user edits one string attribute of a third collection with no relationship but with the same permissions (document security, create on the collection, read and update for the user on the document), it works.

brittle prism
#

@faint swallow did you found the solution?

#

seems I am facing the same issue... it looks like I need to grant update access to all the related Document...

brittle prism
faint swallow
#

Hi, unfortunately no
I think this is a bug in Appwrite but I haven't had the time to debug it

A quick and dirty solution is to create a function with full API permission that will do the update
And you check inside the function that the user has the correct permission

faint swallow
brittle prism
#

oh thank you for confirming

verbal marsh
faint swallow
# verbal marsh We'll need to try and reproduce this. What type of relationship do you have?

It's a two-way "one to many" relationship from collection A towards collection B.
I encourage you to check the code I sent earlier in the discussion, because it seems in this particular case Appwrite fails to identify that the document rule applies (it throws the error in a if code where it checks for !$documentSecurity while both of the collections have document-security enabled).

verbal marsh
# faint swallow It's a two-way "one to many" relationship from collection A towards collection B...

so i just tried to reproduce this, but it works fine for me.

Collection A:

{
    "$id": "level1",
    "$createdAt": "2023-07-06T20:48:10.666+00:00",
    "$updatedAt": "2023-07-08T22:14:20.553+00:00",
    "$permissions": [
        "create(\"any\")"
    ],
    "databaseId": "one-to-many",
    "name": "Level 1",
    "enabled": true,
    "documentSecurity": true,
    "attributes": [
        {
            "key": "level2",
            "type": "relationship",
            "status": "available",
            "required": false,
            "array": false,
            "relatedCollection": "level2",
            "relationType": "oneToMany",
            "twoWay": true,
            "twoWayKey": "level1",
            "onDelete": "restrict",
            "side": "parent"
        },
        {
            "key": "s",
            "type": "string",
            "status": "available",
            "required": false,
            "array": false,
            "size": 10,
            "default": null
        }
    ],
    "indexes": []
}

Collection B:

{
    "$id": "level2",
    "$createdAt": "2023-07-06T20:48:11.025+00:00",
    "$updatedAt": "2023-07-08T22:14:29.193+00:00",
    "$permissions": [
        "create(\"any\")"
    ],
    "databaseId": "one-to-many",
    "name": "Level 2",
    "enabled": true,
    "documentSecurity": true,
    "attributes": [
        {
            "key": "level1",
            "type": "relationship",
            "status": "available",
            "required": false,
            "array": false,
            "relatedCollection": "level2",
            "relationType": "oneToMany",
            "twoWay": true,
            "twoWayKey": "level1",
            "onDelete": "restrict",
            "side": "parent"
        }
    ],
    "indexes": []
}
#

Here's my document in level1:

{
    "s": "asdf",
    "$id": "level1",
    "$createdAt": "2023-07-06T20:49:25.373+00:00",
    "$updatedAt": "2023-07-08T22:16:22.731+00:00",
    "$permissions": [
        "read(\"user:joe\")",
        "update(\"user:joe\")"
    ],
    "level2": [
        {
            "$id": "level2",
            "$createdAt": "2023-07-06T20:49:25.373+00:00",
            "$updatedAt": "2023-07-08T22:16:22.734+00:00",
            "$permissions": [
                "read(\"user:joe\")",
                "update(\"user:joe\")"
            ],
            "$databaseId": "one-to-many",
            "$collectionId": "level2"
        }
    ],
    "$databaseId": "one-to-many",
    "$collectionId": "level1"
}
#

update:

res = await fetch("https://8080-appwrite-integrationfor-sph1lsdai8a.ws-us101.gitpod.io/v1/databases/one-to-many/collections/level1/documents/level1", {
  "headers": headers,
  "referrer": "http://localhost:3000/",
  "referrerPolicy": "strict-origin-when-cross-origin",
  "body": JSON.stringify({data: {s: "as"}}),
  "method": "PATCH",
  "mode": "cors",
  "credentials": "omit"
});
await res.json()
#

response:

{
    "s": "as",
    "$id": "level1",
    "$createdAt": "2023-07-06T20:49:25.373+00:00",
    "$updatedAt": "2023-07-08T22:19:59.848+00:00",
    "$permissions": [
        "read(\"user:joe\")",
        "update(\"user:joe\")"
    ],
    "level2": [
        {
            "$id": "level2",
            "$createdAt": "2023-07-06T20:49:25.373+00:00",
            "$updatedAt": "2023-07-08T22:19:59.851+00:00",
            "$permissions": [
                "read(\"user:joe\")",
                "update(\"user:joe\")"
            ],
            "$databaseId": "one-to-many",
            "$collectionId": "level2"
        }
    ],
    "$databaseId": "one-to-many",
    "$collectionId": "level1"
}
faint swallow
#

The setup seems similar, that's strange.
I'll try spin up a minimal reproductible setup when I'll get some free time.

brittle prism
#

btw I was in version 1.3.4, I just tried to migrate to 1.3.7 and for some reason it's failing...

verbal marsh
brittle prism