owncloud / web

:dragon_face: Next generation frontend for ownCloud Infinite Scale
https://owncloud.dev/clients/web/
GNU Affero General Public License v3.0
427 stars 161 forks source link

[web] Open in web or app banner #9139

Open exalate-issue-sync[bot] opened 1 year ago

exalate-issue-sync[bot] commented 1 year ago

Description

User Stories

Value

Acceptance Criteria

Implementation Note:

Definition of ready

[ ] everybody needs to understand the value written in the user story [ ] acceptance criteria has to be defined [ ] all dependencies of the user story need to be identified [ ] feature should be seen from an end user perspective [ ] user story has to be estimated [ ] story points need to be less then 20

Definition of done

michaelstingl commented 1 year ago

Related:

michaelstingl commented 1 year ago

Android Examples from other Services

android-google-meet android-goto android-goto-installed android-teams android-zoom
Google Meet GoTo Meeting GoTo Meeting (installed) Microsoft Teams Zoom

Elements / features used

  1. Download link
  2. Link to open Android app
  3. Fake "Smart App Banner" (no reliable native Android feature, but tools like smartbanner.js could help)
  4. Redirect to open in App right away

Google Meet link redirects to Play Store 🤔

michaelstingl commented 1 year ago
  • Fake "Smart App Banner" (no reliable native Android feature, but tools like smartbanner.js could help)

More information:

michaelstingl commented 1 year ago
  • Link to open Android app

More information:

michaelstingl commented 1 year ago

iOS Examples from other Services

ios-google-meet ios-goto ios-goto-installed ios-teams-installed ios-zoom-installed
Google Meet GoTo Meeting GoTo Meeting (installed) Microsoft Teams (installed) Zoom (installed)

Elements / features used

  1. Download link
  2. Link to open iOS app
  3. iOS Safari native Smart App Banner
  4. "Universal Links banner" (if you have enabled Universal Links for your domain and the app is already installed on the device, Safari will automatically show a smaller version of the app banner.)
  5. Copies link to clipboard feature/hack, so the iOS apps can retrieve it from there
michaelstingl commented 1 year ago

Users will receive a link like this on their mobile device (mail, messenger etc):

Link opens Web in mobile browser, and performs a request against the unauthenticated tokeninfo endpoint:

% curl -s https://ocis.ocis-traefik.daily.owncloud.works/ocs/v1.php/apps/files_sharing/api/v1/tokeninfo/unprotected/xbRJjSSUUrlmait | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<ocs>
  <meta>
    <status>ok</status>
    <statuscode>100</statuscode>
    <message>OK</message>
  </meta>
  <data>
    <token>xbRJjSSUUrlmait</token>
    <link_url>/s/xbRJjSSUUrlmait</link_url>
    <password_protected>false</password_protected>
    <alias_link>false</alias_link>
    <id>0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51!d485c939-0141-456b-8a97-5bfa9497ddff</id>
    <storage_id>0f1c87f7-92e5-4549-8197-c7ece53e2e87</storage_id>
    <space_id>4c510ada-c86b-4815-8820-42cdf82c3d51</space_id>
    <opaque_id>d485c939-0141-456b-8a97-5bfa9497ddff</opaque_id>
    <path/>
    <space_path/>
    <space_alias/>
    <space_url/>
    <space_type/>
  </data>
</ocs>

From the <id>0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51!d485c939-0141-456b-8a97-5bfa9497ddff</id>, web can generate a link, that gets displayed as the [Open in App] button:

This link will then open the mobile app.

michaelstingl commented 1 year ago

Link opens Web in mobile browser, and performs a request against the unauthenticated tokeninfo endpoint:

  • /ocs/v1.php/apps/files_sharing/api/v1/tokeninfo/unprotected/xbRJjSSUUrlmait

@micbar @tbsbdr @kulmann seems this doesn't work with password protected links:

% curl -s https://ocis.ocis-traefik.daily.owncloud.works/ocs/v1.php/apps/files_sharing/api/v1/tokeninfo/unprotected/qVroPUsyqNgsKAi  | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<ocs>
  <meta>
    <status>ok</status>
    <statuscode>100</statuscode>
    <message>OK</message>
  </meta>
  <data>
    <token>qVroPUsyqNgsKAi</token>
    <link_url>/s/qVroPUsyqNgsKAi</link_url>
    <password_protected>true</password_protected>
    <alias_link>false</alias_link>
    <id/>
    <storage_id/>
    <space_id/>
    <opaque_id/>
    <path/>
    <space_path/>
    <space_alias/>
    <space_url/>
    <space_type/>
  </data>
</ocs>

There it only works when you PROPFIND with basic-auth (link password):

% curl -s 'https://ocis.ocis-traefik.daily.owncloud.works/remote.php/dav/public-files/qVroPUsyqNgsKAi' \
-X 'PROPFIND' \
-H 'Authorization: Basic cHVibGljOjEyMzQ1Ng==' \
--data-binary $'<?xml version="1.0"?>
<d:propfind  xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
  <d:prop>
    <oc:id />
    <oc:privatelink />
  </d:prop>
  </d:propfind>' | xmllint --format -
<?xml version="1.0"?>
<d:multistatus xmlns:s="http://sabredav.org/ns" xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
  <d:response>
    <d:href>/remote.php/dav/public-files/qVroPUsyqNgsKAi/</d:href>
    <d:propstat>
      <d:prop>
        <oc:id/>
        <oc:privatelink/>
      </d:prop>
      <d:status>HTTP/1.1 404 Not Found</d:status>
    </d:propstat>
  </d:response>
  <d:response>
    <d:href>/remote.php/dav/public-files/qVroPUsyqNgsKAi/Photos-001.zip</d:href>
    <d:propstat>
      <d:prop>
        <oc:id>0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51!d485c939-0141-456b-8a97-5bfa9497ddff</oc:id>
        <oc:privatelink>https://ocis.ocis-traefik.daily.owncloud.works/f/0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51%21d485c939-0141-456b-8a97-5bfa9497ddff</oc:privatelink>
      </d:prop>
      <d:status>HTTP/1.1 200 OK</d:status>
    </d:propstat>
  </d:response>
</d:multistatus>

It doesn't work with the credentials from the owner of the resource:

% curl -s 'https://ocis.ocis-traefik.daily.owncloud.works/remote.php/dav/public-files/qVroPUsyqNgsKAi' \
-X 'PROPFIND' \
-H 'Authorization: Bearer REDACTED' \
--data-binary $'<?xml version="1.0"?>
<d:propfind  xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
  <d:prop>
    <oc:id />
    <oc:privatelink />
  </d:prop>
  </d:propfind>' | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<d:error xmlns:d="DAV" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
  <s:message>No 'Authorization: Basic' header found</s:message>
</d:error>
michaelstingl commented 1 year ago

The owner of a resource could query /ocs/v1.php/apps/files_sharing/api/v1/shares and filter the result for the token>qVroPUsyqNgsKAi</token>:

% curl -s 'https://ocis.ocis-traefik.daily.owncloud.works/ocs/v1.php/apps/files_sharing/api/v1/shares?include_tags=false&share_types=3' \
-H 'Authorization: Bearer REDACTED' | xmllint --format - | grep -E 'token|space_id|item_source'
      <token>qVroPUsyqNgsKAi</token>
      <space_id>0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51!4c510ada-c86b-4815-8820-42cdf82c3d51</space_id>
      <item_source>0f1c87f7-92e5-4549-8197-c7ece53e2e87$4c510ada-c86b-4815-8820-42cdf82c3d51!d485c939-0141-456b-8a97-5bfa9497ddff</item_source>

Then construct the link with <space_id> and <item_source>

michaelstingl commented 10 months ago

Implementation Note:

  • ipadOS user agent gets announced as "MacOS"
  • mabye use library to detect ipads as they get annonced as "MacOS" (ex. lib "Mobile Detect")

Doesn't work reliable:

D712806F-EFAC-4471-BB5C-983411848C06_4_5005_c

[Log]  ownCloud Web UI 8.0.0-alpha.4  (index.html-3c2aed60.mjs, line 1)
[Log]  Infinite Scale 4.0.0+337dca17e Community  (index.html-3c2aed60.mjs, line 1)
michaelstingl commented 10 months ago

Elements / features used

  1. Download link

How can I go to the install page, im case the app isn't installed yet?

EA0F6944-8C4E-4629-B6ED-313C8951A0F1_4_5005_c

[Log]  ownCloud Web UI 8.0.0-alpha.4  (index.html-3c2aed60.mjs, line 1)
[Log]  Infinite Scale 4.0.0+337dca17e Community  (index.html-3c2aed60.mjs, line 1)
michaelstingl commented 10 months ago

Config docs:

michaelstingl commented 10 months ago

FR for config option to disable: