Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharing NG #6993

Open
21 of 22 tasks
exalate-issue-sync bot opened this issue Aug 8, 2023 · 9 comments
Open
21 of 22 tasks

Sharing NG #6993

exalate-issue-sync bot opened this issue Aug 8, 2023 · 9 comments

Comments

@exalate-issue-sync
Copy link

exalate-issue-sync bot commented Aug 8, 2023

Goal

  • Same Sharing Roles across all clients
  • Sharing Roles can be changed on a single source of truth (the instance)
  • Foundation for OCM (Federated Shares)
  • Elevate or Full-Deny of access permissions within Spaces

⚠️ Note:

  • This can mean to drop OCS Share API *
  • This can mean to drop the support of Web UI for OC10

*needs deprecation notice 6 month prior for CERN

Images

expected

problem elevate permissions via sharing

Stories

Sharing

Links

Users

@fschrempf
Copy link

Hi, I'm currently trying out oCIS and in the long run I would like to migrate from Nextcloud + NC Groupfolders. The changes described above look like an equivalent for NC Groupfolder ACL permissions and this is what I'm currently missing for oCIS.

It would be great to see this implemented and if I can help in some way I would like to try and do so.

IMHO the question about the "conflict" between share permissions and space permissions described in the second image above is important. In NC this issue causes a lot of confusion as users can see the same content of a directory once as share and once inside the groupfolder (=space).

Would it be possible to prevent the conflict in the first place and do a check for overlapping shares and space permission for each affected user whenever shares/permissions are changed?

Another thing to consider is the use-case where we have a space with ("many") subdirectories and each subdirectory should be visible only to certain stakeholders. Here is an example:

Groups:

  • Meeting Team (contains all members of the subgroups)
    • Meeting Welcome Team
    • Meeting Organisation Team
    • Meeting Finance Team

Space:

Space "Meeting 2023"             # should be visible to all groups
├─ Subdirectory "Shared"         # should be writeable to all groups
├─ Subdirectory "Organisation"   # should only be visible for group "Meeting Organisation Team"
├─ Subdirectory "Welcome"        # should only be visible for groups "Meeting Welcome Team" and
│                                # "Meeting Organisation Team"
└─ Subdirectory "Finance"        # should only be visible for groups "Meeting Finance Team" and
                                 # "Meeting Organisation Team"

Given the conditions outlined in the first image above, I think the permissions would need to look like this:

Space "Meeting 2023"
│    * view-only permissions for "Meeting Team"
├─ Subdirectory "Shared"
│    * write permissions for "Meeting Team"
├─ Subdirectory "Organisation"
│    * deny all permissions for "Meeting Team"
│    * write permissions for "Meeting Organisation Team"
├─ Subdirectory "Welcome"
│    * deny all permissions for "Meeting Team"
│    * write permissions for "Meeting Organisation Team"
│    * write permissions for "Meeting Welcome Team"
└─ Subdirectory "Finance"
     * deny all permissions for "Meeting Team"
     * write permissions for "Meeting Organisation Team"
     * write permissions for "Meeting Finance Team"

For hiding subdirectories you need to use the parent group "Meeting Team" to first deny all permissions and then increase permissions for certain subgroups.

When scaling up to n subdirectories (each accessible only to one group) with m groups, we would get n * 2 permission rules.

If there is no group hierarchy available it looks different. Given groups like this:

  • Meeting Welcome Team
  • Meeting Organisation Team
  • Meeting Finance Team

We would get:

Space "Meeting 2023"
│    * view-only permissions for "Welcome Team"
│    * write permissions for "Organisation Team"
│    * view-only permissions for "Finance Team"
├─ Subdirectory "Shared"
│    * write permissions for "Welcome Team"
│    * write permissions for "Finance Team"
│    * (inherited) write permissions for "Organisation Team"
├─ Subdirectory "Organisation"
│    * deny all permissions for "Welcome Team"
│    * deny all permissions for "Finance Team"
│    * (inherited) write permissions for "Organisation Team"
├─ Subdirectory "Welcome"
│    * deny all permissions for "Finance Team"
│    * write permissions for "Welcome Team"
│    * (inherited) write permissions for "Organisation Team"
└─ Subdirectory "Finance"
     * deny all permissions for "Welcome Team"
     * write permissions for "Finance Team"
     * (inherited) write permissions for "Organisation Team"

Note that "deny all" permissions are needed for each subdirectory and each group that has access to the space but not to the specific subdirectory. When scaling up to n subdirectories (each accessible only to one group) with m groups, we would get n * (m-1) permission rules.

To simplify this and make the rules more intuitive we could use something like an implicit "view-tree-only" permission. This means that someone that has access to a subdirectory of a space would automatically get the permission to see the directory tree above this subdirectory up until the root of the space (but none of the siblings on any level).

Space "Meeting 2023"
│    * write permissions for "Organisation Team"
│    * (implicit) view-tree-only permission for "Welcome Team"
│    * (implicit) view-tree-only permission for "Finance Team"
├─ Subdirectory "Shared"
│    * write permissions for "Welcome Team"
│    * write permissions for "Finance Team"
├─ Subdirectory "Organisation"
│    * (inherited) write permissions for "Organisation Team"
├─ Subdirectory "Welcome"
│    * write permissions for "Welcome Team"
│    * (inherited) write permissions for "Organisation Team"
└─ Subdirectory "Finance"
     * write permissions for "Finance Team"
     * (inherited) write permissions for "Organisation Team"

I think this could greatly reduce the amount of explicit permission rules that are required and therefore make the whole thing much more simple to handle.

Sorry for the lengthy post and I hope this makes some sense at all to someone. ;)

@micbar
Copy link
Contributor

micbar commented Nov 21, 2023

Lifecycle of a share

libregraph API spec for the sharing ADR in #6995

When following a share lifecycle, the following OCS requests can be replaced with these libregraph counterparts:

List shares on a resource (includes sharing options)

OCS: web calls two endpoints:

  • /ocs/v1.php/apps/files_sharing/api/v1/shares?path={space-relative-path}&space_ref={space-id}&reshares=true
  • /ocs/v1.php/apps/files_sharing/api/v1/shares?path={space-relative-path}&space_ref={space-id}&shared_with_me=true

ms graph: /drives/{drive-id}/items/{drive-item-id}/permissions

{
    "value": [
        {
            "id": "collaborative-share-id",
            "roles": [
                "write"
            ],
            "grantedToV2": {
                "user": {
                    "displayName": "Albert Einstein",
                    "id": "4c510ada-c86b-4815-8820-42cdf82c3d51"
                }
            },
        },
        {
            "id": "public-link-share-id",
            "roles": [
                "read"
            ],
            "link": {
                "webUrl": "https://cloud.example.com/s/CMXOrzoFODpHKsS"
            }
        }
    ]
}

libre graph: for now we stick to two kinds of permissions:

  • grantedToV2 for internal user or group shares
  • link for public link shares
    jfd: roles are currently hardcoded to read, write and owner. We can make them customizable but I'll show that at the end of this description
{
    "value": [
        {
            "id": "collaborative-share-id",
            "roles": [
                "write"
            ],
            "grantedToV2": {
                "user": {
                    "displayName": "Albert Einstein",
                    "id": "4c510ada-c86b-4815-8820-42cdf82c3d51"
                }
            },
        },
        {
            "id": "public-link-share-id",
            "roles": [
                "read"
            ],
            "link": {
                "webUrl": "https://cloud.example.com/s/CMXOrzoFODpHKsS"
            }
        }
    ]
}

Search for recipient (not part of this PR)

OCS: /ocs/v2.php/apps/files_sharing/api/v1/sharees?search=einst&itemType=(folder|file)&page=1&perPage=200&format=json
ms graph: /me/people?$search="einst" is used to interact with users that are relevant or in a working-with relationship. The returned list of person entities has a personType property to differentiate types of groups and users.
libre graph: /me/people?$search="einst" is the only endpoint we need, I think. For now, a $search="einst" parameter can be used instead of the OCS sharee call.

Note: There is a difference between $search="foo bar" and $search=foo bar. To mimic OCS the request has to quote the typed in string.*

Create a share with user or group

OCS:

POST ocs/v1.php/apps/files_sharing/api/v1/shares

shareType=0
shareWith=marie
path=/Neuer Ordner
space_ref=storage-users-1$some-admin-user-id-0000-000000000000!71beebf5-0057-4104-a814-bb49712eaab9
permissions=31
role=editor

ms graph: sharing wit a user is done by posting an invite

POST /drives/{drive-id}/items/{drive-item-id}/invite

{
    "requireSignIn": true,
    "recipients": [
        {
            "email": "[email protected]"
        }
    ],
    "roles": [
        "read"
    ]
}

response:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(permission)",
    "value": [
        {
            "@odata.type": "#microsoft.graph.permission",
            "id": "r_mJa3kBqBtkotIl8tWt9nVA2L1",
            "roles": [
                "read"
            ],
            "shareId": "s!BFB3CkuhRCbBgmcZvWieFTBrBGQ",
            "expirationDateTime": "0001-01-01T00:00:00Z",
            "hasPassword": false,
            "grantedToV2": {
                "user": {
                    "id": "[email protected]"
                }
            },
            "invitation": {
                "email": "[email protected]",
                "signInRequired": true
            },
            "link": {
                "webUrl": "https://1drv.ms/f/s!BFB3CkuhRCbBgmcZvWieFTBrBGQ"
            }
        }
    ]
}

It seems the response does not use grantedToV2. And when requireSignIn is left out or false it will happily create a link webUrl that allows browsing the file.

libre graph: sharing wit a user is done by posting an invite. While ms graph uses email to identify a recipient libre graph assumes internal shares are created using the objectId (the users id)

POST /drives/{drive-id}/items/{drive-item-id}/invite

{
    "requireSignIn": true,
    "recipients": [
        {
            "objectId": "4c510ada-c86b-4815-8820-42cdf82c3d51"
        }
    ],
    "roles": [
        "read"
    ]
}

response:

{
    "value": [
        {
            "id": "8c5ed185-1fcb-4c5a-8569-b9ed04293204",
            "roles": [
                "read"
            ],
            "grantedToV2": {
                "user": {
                    "id": "4c510ada-c86b-4815-8820-42cdf82c3d51"
                }
            },
        }
    ]
}

jfd: multiple recipients can be sent in the same request. Each will receive a dedicated permissions object with their own id. WChen an error occurs a 207 multistatus response will be returned, similar to https://learn.microsoft.com/en-us/graph/api/site-follow?view=graph-rest-1.0&tabs=http#response-1 which shows an examplo where one of the entries contains an error
request:

POST /drives/{drive-id}/items/{drive-item-id}/invite

{
    "recipients": [
        {
          "objectId": "4c510ada-c86b-4815-8820-42cdf82c3d51"
        },
        {
          "objectId": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"
        }
    ],
    "roles": [
        "read"
    ]
}

response:

{
  "value": [
    {
      "id": "81d5bad3-3eff-410a-a2ea-eda2d14d4474",
      "roles": [
        "write"
      ],
      "grantedToV2": [
        {
          "user": {
            "id": "4c510ada-c86b-4815-8820-42cdf82c3d51",
            "displayName": "Albert Einstein"
          }
        }
      ]
    },
    {
      "id": "b470677e-a7f5-4304-8ef5-f5056a21fff1",
      "error": {
        "@odata.type": "#odata.error.main",
        "code": "invalidRequest",
        "message": "The user id that is provided in the request is incorrect",
        "innerError": {
            "code": "itemNotFound",
            "errorType": "expected",
            "message": "Unknown user id b470677e-a7f5-4304-8ef5-f5056a21fff1 ",
        }
      }
    }
  ]
}

Shared by me

List shares created by the currently logged in user
OCS: is called Shared With Others, see below
ms graph: odata query not implemented
onedrive web: can list shares by me in the web ui. maybe something is coming to ms graph as well?
libre graph: /me/drive/sharedByMe (only includes shares created by the current user)

Shared with others (not part of this PR)

Includes shares in project spaces that can be managed by the current user because he is a manager of the space. He does not need to be the creator of the share.
OCS: /ocs/v1.php/apps/files_sharing/api/v1/shares?reshares=true&include_tags=false&share_types=0,1,4,6
ms graph: odata query not implemented
libre graph: does not exist, but we could add a new /me/drive/sharedWithOthers endpoint

Note: the OCS share_types are 0 = User, 1 = Group, 3 = public link, 4 = guest, 6 = federated share, 7 = federated group / space member user (OH great we have a clash here), 8 = space member group.

Hint: There is a difference in the concept of shares. In OC10 shares are tied to a user. In OCIS they are tied to a space. The Owner/All managers of a space can collaboratively manage all shares in a personal/project space.

Shared with me

As the recipient you want to get a list of all driveItems that have been shared with you.
OCS: /ocs/v1.php/apps/files_sharing/api/v1/shares?include_tags=false&state=all&shared_with_me=true
ms graph: /me/drive/sharedWithMe
libre graph: /me/drive/sharedWithMe
The endpoint returns a collection(driveItem) that contains both: mounted and unmounted driveItems. shared driveItems are wrapped in another driveItem representing the mountpoint as on the ms graph API. But there are two deviations from the ms graph API:

  1. Shared driveItems that have not been mounted are not wrapped by another drive item. The ms graph api always wraps the shared driveItem. We do not want to do that on the fly as the driveItem representing the mountpoint would not have a parent id as it is unmounted. We will only wrap the shared driveItem with a mount point if the share has been created.
  2. libre graph for now does not use the shared property but expands the permissions relation as it contains all necessary information. This might change if we think the shared property is enough to show the necessary indicators. It would be faster than listing all details of the permission.
  3. libre graph uses a @UI.hidden annotation on driveItems to indicate
{
  "value": [
    {
      "id": "u-u-id-of-mountpoint",
      "name": "November-December Ad Proposals.pptx",
      "size": 100984,
      "parentReference": {
        "driveType": "personal",
        "driveId": "u-u-id-of-drive-containing-the-pointpoint",
        "id": "parent-u-u-id"
      },
      "remoteItem": {
        "id": "u-u-id-of-shared-driveItem",
        "name": "November-December Ad Proposals.pptx",
        "size": 100984,
        "parentReference": {
          "driveType": "personal",
          "driveId": "u-u-id-of-drive-containing-the-item"
          // no "id" because recipient is not allowed to see parent
        },
        "permissions": [
          {
            "@UI.hidden": false,
            "id": "92f276ac-827a-40c1-9d9c-bb41a628ce71",
            "roles": [
              "write"
            ],
            "grantedToV2": {
              "user": {
                "displayName": "Jörn Dreyer",
                "id": "c12644a14b0a7750"
              }
            }
          }
        ]
      }
    },
    {
      "id": "7fd82e03-09af-4b38-8d36-c7f7ec83cd99",
      "name": "Marketing Term Successes International.xlsx",
      "size": 17776,
      "parentReference": {
        "driveType": "personal",
        "driveId": "u-u-id-of-drive-containing-the-item"
        // no "id" because recipient is not allowed to see parent
      },
      "permissions": [
        {
          "@UI.hidden": false,
          "id": "477731b4-56a6-4f58-9530-2e08bdf52df5",
          "roles": [
            "write"
          ],
          "grantedToV2": {
            "user": {
              "displayName": "Jörn Dreyer",
              "id": "c12644a14b0a7750"
            }
          }
        }
      ]
    },
    {
      "id": "a7d033f9-6093-43bb-91a7-bc82265e6a7f",
      "name": "Irrelevant Marketing Term Successes International.xlsx",
      "size": 176536587,
      "parentReference": {
        "driveType": "personal",
        "driveId": "u-u-id-of-drive-containing-the-item"
        // no "id" because recipient is not allowed to see parent
      },
      "permissions": [
        {
          "@UI.hidden": true,
          "id": "5277be2e-db85-4d11-9a6c-28853142f279",
          "roles": [
            "write"
          ],
          "grantedToV2": {
            "user": {
              "displayName": "Jörn Dreyer",
              "id": "c12644a14b0a7750"
            }
          }
        }
      ]
    }
  ]
}

jfd: we cannot put the @UI.hidden property on the drive item directly, because it would mean the driveItem was hidden. So we put it on the permissions property. That hidden flag can be toggled.

Accept/Reject a share / an invite

OCS:

  • Accept POST ocs/v2.php/apps/files_sharing/api/v1/shares/pending/{share-id}
  • Deny DELETE ocs/v2.php/apps/files_sharing/api/v1/shares/pending/{share-id}
    ms graph: /sharedWithMe will list all shares, but
  • I cannot see a property that shows the mountpoint ... the parentReference only contains
"parentReference": {
    "driveId": "c12644a14b0a7750",
    "driveType": "personal"
},

libre graph: mount shares in the share jail by creating a driveItem using a POST /drives/{sharejailid}/items request:

{
  "name": "Einsteins project share",
  "remoteItem": {
    "id": "{drive-item-id}"
  }
}

This request can check if the current user has access to the given drive item and will 'mount'/ accept it with the name "Einsteins project share". In theory we could add a remoteItem anywhere in a drive like in OC10, but it is a product decision to collect them in the dedicated virtual share jail drive.

The mountpoint can be deleted/rejected by sending a DELETE /drives/{drive-item-id} where {drive-item-id} is the id of the drive item representing the mount point, not the remote item.

Create a public link

ms graph

POST /drives/{drive-id}/items/{drive-item-id}/createLink

{
    "type": "view",
    "scope": "anonymous"
}

response:

{
    "id": "{permission-id}",
    "link": {
        "type": "view",
        "webUrl": "https://1drv.ms/f/s!AlB3CkuhRCbBgmde472f8-qxYdg",
        "application": {
            "id": "4c1ad100"
        }
    }
}

Update shares / links

ms graph:
jfd: same as libregraph but I tried changing the role ... we'll just not go there for now
The role does affect the ui. It now shows upload elements even for non logged in users. The link type is still view. When trying to upload a file the web ui will try to log you in before making the request. The link type cannot be changed: in the UI there is a hint "This setting can't be changed. Create a new link if you need different permissions.". I guess this is to prevent changing permissions on existing links?

libre graph:

PATCH /drives/{drive-id}/items/{drive-item-id}/permissions/{permission-id}

{
    "link": {
        "type": "edit"
    }
}

response

{
    "id": "{permission-id}",
    "link": {
        "type": "edit",
        "webUrl": "https://1drv.ms/f/s!AlB3CkuhRCbBgmde472f8-qxYdg",
        "application": {
            "id": "4c1ad100"
        }
    }
}

For links we ignore the role and instead set the link type. ms graph has a lot predefined: https://learn.microsoft.com/en-us/graph/api/listitem-createlink?view=graph-rest-beta&tabs=http#link-types

Type value Description
internal Only people who are invited.
view People can view and download.
edit People can view, download, upload, edit, move, add and delete
blocksDownload Creates a read-only link that blocks download to the item. Could be SecureView in the future. Not implemented yet.
createOnly People can only upload, existing content is not revealed (folders only)
upload People can upload, download and view (folders only)

Delete shares / links

OCS DELETE ocs/v1.php/apps/files_sharing/api/v1/shares/{share-id}
libre graph DELETE /drives/{drive-id}/items/{drive-item-id}/permissions/{permission-id}

Further reading

It follows the MS Graph API, documented here:

Listing shares incoming / outgoing shares:

  • list shared with me https://learn.microsoft.com/en-us/graph/api/drive-sharedwithme
  • list shared with others has no official andpoint, but the semantically matching request might be https://graph.microsoft.com/v1.0/me/drive/items?$filter=shared ne null. It works by matching all driveItems that have no sharing facet. However, it is not implemented in ms graph. Maybe because it is not clear that /v1.0/me/drive/items works on ALL drives. Semantically, it should only list the shared drive items on the users personal drive. To match drive items on all drives the user has access to https://graph.microsoft.com/v1.0/drives?$expand=items&$filter=items/any(property:property/shared+ne+null) could be used to get a list of all drives that have shared drive items and expand the items. This is not allowed on the ms graph api.
    What does work is https://graph.microsoft.com/v1.0/me/drive/root/search(q='*')?filter=shared+ne+null but it is slow as it relies on the search() function. I'd go with the semantically correct version.

interesting sidenote

@micbar
Copy link
Contributor

micbar commented Nov 21, 2023

@TheOneRing @felix-schwarz @jesmrec @michaelstingl I posted a typical share lifecycle.

The details of the new API are getting clearer day by day now. I am really looking forward. We will get there 😄

@fschade
Copy link
Contributor

fschade commented Nov 27, 2023

@micbar

can you explain what the endpoint

Add POST drive/{drive-id}/items and DELETE drive/{drive-id}/items/{item-ID}

should do in the sharing ng context?

@felix-schwarz
Copy link

  • Regarding Shared by me / Shared with others: what does the response look like?
  • Can you explain the difference between creating a share with requireSignIn set to false and creating a public link?
  • Can you explain the reasoning behind not using roles for public links, but use a pre-defined set of types instead?
  • What about APIs for roles? You mentioned that roles are currently hardcoded to read, write and owner. We can make them customizable but I'll show that at the end of this description, but I can't seem to find that part.

@micbar
Copy link
Contributor

micbar commented Nov 29, 2023

  • Regarding Shared by me / Shared with others: what does the response look like?

You will get a list of drive items with an array of permissions https://owncloud.dev/libre-graph-api/#/me.drive/ListSharedByMe

  • Can you explain the difference between creating a share with requireSignIn set to false and creating a public link?

Public links are not created via the invite endpoint. Please check the swagger Ui https://owncloud.dev/libre-graph-api/#/drives.permissions/CreateLink

  • Can you explain the reasoning behind not using roles for public links, but use a pre-defined set of types instead?

Because they are the same like on OneDrive and we currently see no need to make that dynamic. The current efforts focus on shifting all responsibility to the server and make hatdcoded client side role mappings obsolete.

  • What about APIs for roles? You mentioned that roles are currently hardcoded to read, write and owner. We can make them customizable but I'll show that at the end of this description, but I can't seem to find that part.

There are APIs to list roles and role permissions. The swagger ui provides a lot of explanations and examples. https://owncloud.dev/libre-graph-api/#/roleManagement/ListPermissionRoleDefinitions

They will not be configurable in the first iteration. But that has no impact on the API, because they should not be configurable at runtime.

@felix-schwarz
Copy link

felix-schwarz commented Nov 30, 2023

  • Regarding Shared by me / Shared with others: what does the response look like?

You will get a list of drive items with an array of permissions https://owncloud.dev/libre-graph-api/#/me.drive/ListSharedByMe

Thanks! Looking at the provided example below, is value.id the ID of the share/permission? Or the File ID of the shared item? If it's the former: from where can a client get the File ID of the shared item?

{
  "value": [
    {
      "id": "78363031-03ef-4eda-84a2-243a691a13cd",
      "createdDateTime": "2020-02-19T14:23:25.52Z",
      "eTag": "aQzEyNjQ0QTE0QjBBNzc1MCExMzc5LjQ",
      "lastModifiedDateTime": "2021-09-03T14:09:25.503Z",
      "name": "March Proposal.docx",
      "parentReference": {
        "driveId": "1991210caf",
        "driveType": "personal"
      }
  • Can you explain the difference between creating a share with requireSignIn set to false and creating a public link?

Public links are not created via the invite endpoint. Please check the swagger Ui https://owncloud.dev/libre-graph-api/#/drives.permissions/CreateLink

I understand that public links should be created via createLink, but am wondering what invite's requireSignIn is there for then. Since, if I'm able to create a link, via which someone else can view content without having to sign in, that sounds like the description of a public link to me.

  • Can you explain the reasoning behind not using roles for public links, but use a pre-defined set of types instead?

Because they are the same like on OneDrive and we currently see no need to make that dynamic. The current efforts focus on shifting all responsibility to the server and make hatdcoded client side role mappings obsolete.

Right now, the iOS app can internally use roles for public links and user/group shares - and use the same UI code for public links as for user/group shares because the current/OC10 API uses the same permission model and endpoint as user/group shares.

The way I understand the proposed new API now (and please correct me if I'm wrong), public links and user/group shares no longer share a common permission model or semantic, but there's now distinct concepts for the two:

  • roles for user/group shares (provided by the server)
  • share types for public links (needs to be hardcoded, including localized descriptions)

Advantages I'd have seen in adopting roles for public links as well would have been that

  • code could continue to be shared for both public links and user/group shares
  • that the server would have full control over what types of public links users can create by including or excluding roles for public link types in the server-provided list of possible roles.

@micbar
Copy link
Contributor

micbar commented Dec 4, 2023

Advantages I'd have seen in adopting roles for public links as well would have been that

code could continue to be shared for both public links and user/group shares
that the server would have full control over what types of public links users can create by including or excluding roles for public link types in the server-provided list of possible roles.

I see. From the server POV shares and public links are different. So i would not advise to treat them like they are the same.

Biggest differences:

  • No user context
  • Different Permissions (only a subset of permissions is possible because of the missing user context)
  • Password Protection
  • Password Policy
  • Different URL

Thanks! Looking at the provided example below, is value.id the ID of the share/permission? Or the File ID of the shared item? If it's the former: from where can a client get the File ID of the shared item?

The main entity is a driveItem, which is a file or a folder. The id of the driveItem is always the fileID. The permissions are a sub entity of the driveItem, and the permission id is equivalent to the shareID.

@butonic
Copy link
Member

butonic commented Jan 23, 2024

To clarify for the short term:

  • We will change the resource id of mountpoints from the current {sharesstorageproviderid}${sharejailid}!{shareid} to {sharesstorageproviderid}${sharejailid}!{resourceid of shared item}. Currently, the shareid is {providerid}:{spaceid}:{shareid}. We want to change it to be {providerid}:{spaceid}:{node/opaque id}. The Encoding / Decoding with : is only used by the jsoncs3 share manager. Unfortunately, we cannot change the implementation of the jsoncs3 share manager directly, because we would no longer be able to persist multiple shares per resource.
    The plan is to replace the shareid with the resourceid on a higher level, until we can change the CS3 API to reflect this change as well. AFAICT we will need the graph API as well as webdav (or rather tha sharesstorageprovider) to rewrite ids.

  • The @ui.hidden as well as @client.synchronize flags will become part of the driveItem in the /me/sharedWithMe response. It will neither be part of the remoteItem, nor a permission.

  • @ui.hidden should be @UI.Hidden as per https://sap.github.io/odata-vocabularies/vocabularies/UI.html#:~:text=Hidden

Long Term changes on the CS3 API:

  • Shares should better reflect the graph API concept of a remoteItem? It should contain multiple permissions. Then hidden, synced and mountpoint would become properties of a share, rather than the current hack where we set these porperties on all shares of a remoteItem. The current shares would become permissions or maybe grants which is the term already used on the CS3 API when forwarding a share to the storageprovider.

  • Maybe the share manager should become the list of spaces and shares a user has access to. It should answer the question what are the spaces I have access to efficiently per user. Currently, space access is managed by bypassing the gateway and the share manager. The share manager should be made aware of spaces as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants