Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
53b50a6
Create v2 routes
Altahrim Aug 16, 2023
6fb3176
Wrap-up changes for updated subfolders
artonge Mar 20, 2023
d352a4c
Use header to provide e2e-token
artonge May 23, 2023
506b059
Use major.minor for api-versions in capabilities
artonge May 23, 2023
54d8730
Run psalm:fix
artonge May 23, 2023
6ae2a2a
Update API doc
artonge May 23, 2023
cc9569f
Prevent access to set and delete endpoints without valid lock token
artonge May 24, 2023
6a5f7f8
Allow to abort changes during unlock
artonge Jun 1, 2023
c4ea825
Add support for X-NC-E2EE-COUNTER
artonge Jun 1, 2023
04cc8a2
Store signature on metadata save
artonge Jul 3, 2023
c1e7754
Check if required headers are set
artonge Jul 5, 2023
4162a78
Update api.md for new headers
artonge Jul 17, 2023
256cd45
REMOVE ME: temporary fix to allow both routes on same endpoint
Altahrim Aug 24, 2023
f6f048e
Fix leave share for root folder
Altahrim Aug 30, 2023
f8bdb0e
Adapt filedrop to v2 routes
artonge Aug 31, 2023
959cdfe
Adapt filedrop to v2
artonge Jan 8, 2024
e8395f2
Add default mimetype
artonge Jan 11, 2024
c3fd101
Remove triple base64 encoding
artonge Jan 11, 2024
4ab8f26
Use top e2ee folder to retrieve users list in public shares
artonge Jan 15, 2024
92354da
Correctly validate lock state
artonge Jan 16, 2024
c24e620
Run cs:fix
artonge Jan 16, 2024
93e9095
Fix psalm errors
artonge Jan 16, 2024
b698288
Fix lint error
artonge Jan 16, 2024
dbd54e5
Fix phpUnit tests
artonge Jan 16, 2024
6811234
Fix eslint error
artonge Jan 17, 2024
0f33bcc
Fix php unit tests
artonge Jan 17, 2024
c8f6c62
Expose all routes to v2
artonge Jan 17, 2024
4d5f0d0
Move folder lock to the backend for filedrops
artonge Jan 18, 2024
8ea6b40
Add node workflows
artonge Jan 18, 2024
7787c44
Fix phpunit tests
artonge Jan 18, 2024
d856671
Ignore missing signature on v2 endpoint when the metadata is not in v2
artonge Jan 23, 2024
e79f351
Return 403 when old client access version 2.0 encrypted folders
artonge Jan 25, 2024
e574e9c
Improve readability of isLocked return condition
artonge Jan 31, 2024
d44d396
Remove support for e2e-token in header in PUT v1/meta-data
artonge Jan 31, 2024
798ad3f
Apply review suggestions
artonge Jan 31, 2024
f585bf1
Compile assets
artonge Jan 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/node-when-unrelated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# Use node together with node-when-unrelated to make eslint a required check for GitHub actions
# https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks

name: Node

on:
pull_request:
paths-ignore:
- '.github/workflows/**'
- 'src/**'
- 'appinfo/info.xml'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '**.js'
- '**.ts'
- '**.vue'
push:
branches:
- main
- master
- stable*

concurrency:
group: node-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build:
permissions:
contents: none

runs-on: ubuntu-latest

name: node
steps:
- name: Skip
run: 'echo "No JS/TS files changed, skipped Node"'
71 changes: 71 additions & 0 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization

name: Node

on:
pull_request:
paths:
- '.github/workflows/**'
- 'src/**'
- 'appinfo/info.xml'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '**.js'
- '**.ts'
- '**.vue'
push:
branches:
- main
- master
- stable*

permissions:
contents: read

concurrency:
group: node-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

name: node
steps:
- name: Checkout
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2

- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
with:
fallbackNode: '^16'
fallbackNpm: '^7'

- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}

- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"

- name: Install dependencies & build
run: |
npm ci
npm run build --if-present

- name: Check webpack build changes
run: |
bash -c "[[ ! \"`git status --porcelain `\" ]] || (echo 'Please recompile and commit the assets, see the section \"Show changes on failure\" for details' && exit 1)"

- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention
43 changes: 26 additions & 17 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,31 @@

return [
'ocs' => [
['name' => 'Key#setPrivateKey', 'url' => '/api/v1/private-key', 'verb' => 'POST'],
['name' => 'Key#getPrivateKey', 'url' => '/api/v1/private-key', 'verb' => 'GET'],
['name' => 'Key#deletePrivateKey', 'url' => '/api/v1/private-key', 'verb' => 'DELETE'],
['name' => 'Key#createPublicKey', 'url' => '/api/v1/public-key', 'verb' => 'POST'],
['name' => 'Key#getPublicKeys', 'url' => '/api/v1/public-key', 'verb' => 'GET'],
['name' => 'Key#deletePublicKey', 'url' => '/api/v1/public-key', 'verb' => 'DELETE'],
['name' => 'Key#getPublicServerKey', 'url' => '/api/v1/server-key', 'verb' => 'GET'],
['name' => 'MetaData#setMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'POST'],
['name' => 'MetaData#getMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'GET'],
['name' => 'MetaData#updateMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'PUT'],
['name' => 'MetaData#deleteMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'DELETE'],
['name' => 'MetaData#addMetadataFileDrop', 'url' => '/api/v1/meta-data/{id}/filedrop', 'verb' => 'PUT'],
['name' => 'Encryption#removeEncryptedFolders', 'url' => '/api/v1/encrypted-files', 'verb' => 'DELETE'],
['name' => 'Encryption#setEncryptionFlag', 'url' => '/api/v1/encrypted/{id}', 'verb' => 'PUT'],
['name' => 'Encryption#removeEncryptionFlag', 'url' => '/api/v1/encrypted/{id}', 'verb' => 'DELETE'],
['name' => 'Locking#lockFolder', 'url' => '/api/v1/lock/{id}', 'verb' => 'POST'],
['name' => 'Locking#unlockFolder', 'url' => '/api/v1/lock/{id}', 'verb' => 'DELETE'],
# v1
['name' => 'Key#setPrivateKey', 'url' => '/api/v{apiVersion}/private-key', 'verb' => 'POST', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#getPrivateKey', 'url' => '/api/v{apiVersion}/private-key', 'verb' => 'GET', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#deletePrivateKey', 'url' => '/api/v{apiVersion}/private-key', 'verb' => 'DELETE', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#createPublicKey', 'url' => '/api/v{apiVersion}/public-key', 'verb' => 'POST', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#getPublicKeys', 'url' => '/api/v{apiVersion}/public-key', 'verb' => 'GET', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#deletePublicKey', 'url' => '/api/v{apiVersion}/public-key', 'verb' => 'DELETE', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Key#getPublicServerKey', 'url' => '/api/v{apiVersion}/server-key', 'verb' => 'GET', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'V1\MetaData#setMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'POST'],
['name' => 'V1\MetaData#getMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'GET'],
['name' => 'V1\MetaData#updateMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'PUT'],
['name' => 'V1\MetaData#deleteMetaData', 'url' => '/api/v1/meta-data/{id}', 'verb' => 'DELETE'],
['name' => 'V1\MetaData#addMetadataFileDrop', 'url' => '/api/v1/meta-data/{id}/filedrop', 'verb' => 'PUT'],
['name' => 'Encryption#removeEncryptedFolders', 'url' => '/api/v{apiVersion}/encrypted-files', 'verb' => 'DELETE', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Encryption#setEncryptionFlag', 'url' => '/api/v{apiVersion}/encrypted/{id}', 'verb' => 'PUT', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'Encryption#removeEncryptionFlag', 'url' => '/api/v{apiVersion}/encrypted/{id}', 'verb' => 'DELETE', 'requirements' => array('apiVersion' => '[1-2]')],
['name' => 'V1\Locking#lockFolder', 'url' => '/api/v1/lock/{id}', 'verb' => 'POST'],
['name' => 'V1\Locking#unlockFolder', 'url' => '/api/v1/lock/{id}', 'verb' => 'DELETE'],
# v2
['name' => 'MetaData#setMetaData', 'url' => '/api/v2/meta-data/{id}', 'verb' => 'POST'],
['name' => 'MetaData#getMetaData', 'url' => '/api/v2/meta-data/{id}', 'verb' => 'GET'],
['name' => 'MetaData#updateMetaData', 'url' => '/api/v2/meta-data/{id}', 'verb' => 'PUT'],
['name' => 'MetaData#deleteMetaData', 'url' => '/api/v2/meta-data/{id}', 'verb' => 'DELETE'],
['name' => 'MetaData#addMetadataFileDrop', 'url' => '/api/v2/meta-data/{id}/filedrop', 'verb' => 'PUT'],
['name' => 'Locking#lockFolder', 'url' => '/api/v2/lock/{id}', 'verb' => 'POST'],
['name' => 'Locking#unlockFolder', 'url' => '/api/v2/lock/{id}', 'verb' => 'DELETE'],
],
];
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 72 additions & 30 deletions doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@

This are the available OCS API calls for clients to implement end-to-end encryption.
A more general documentation how to use the API can be found [here](https://github.com/nextcloud/end_to_end_encryption/blob/master/doc/api-usage.md).
* [List files and folders with encryption status](#list-files-and-folders-with-encryption-status)
* [Store private key](#store-private-key)
* [Get private key](#get-private-key)
* [Delete private key](#delete-private-key)
* [Sign public key](#sign-public-key)
* [Get public keys](#get-public-keys)
* [Delete public keys](#delete-public-keys)
* [Lock file](#lock-file)
* [Unlock file](#unlock-file)
* [Store-meta-data file](#store-meta-data-file)
* [Get meta-data file](#get-meta-data-file)
* [Update meta-data file](#update-meta-data-file)
* [Delete meta-data file](#delete-meta-data-file)
* [Get server public key](#get-server-public-key)
* [Set encryption flag for a folder](#set-encryption-flag-for-a-folder)
* [Remove encryption flag for a folder](#remove-encryption-flag-for-a-folder)
- [End-to-End Encryption API](#end-to-end-encryption-api)
- [Base URL for all API calls](#base-url-for-all-api-calls)
- [List files and folders with encryption status](#list-files-and-folders-with-encryption-status)
- [Store private key](#store-private-key)
- [Get private key](#get-private-key)
- [Delete private key](#delete-private-key)
- [Sign public key](#sign-public-key)
- [Get public keys](#get-public-keys)
- [Delete public keys](#delete-public-keys)
- [Lock file](#lock-file)
- [Get meta-data file](#get-meta-data-file)
- [Update meta-data file](#update-meta-data-file)
- [Update filedrop property of meta-data file](#update-filedrop-property-of-meta-data-file)
- [Delete meta-data file](#delete-meta-data-file)
- [Get server public key](#get-server-public-key)
- [Set encryption flag for a folder](#set-encryption-flag-for-a-folder)
- [Remove encryption flag for a folder](#remove-encryption-flag-for-a-folder)



Expand All @@ -31,7 +32,7 @@ PROPFIND: `https://<nextcloud>/remote.php/webdav/<folder>/`

**Data:**

xml body:
xml body:
````xml
<d:propfind xmlns:d="DAV:">
<d:prop xmlns:nc="http://nextcloud.org/ns">
Expand Down Expand Up @@ -343,11 +344,22 @@ e2e-token: if you re-try a previously failed upload, use the token from the firs

First try:

`curl -X POST https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/<file-id> -H "OCS-APIRequest:true"`
````shell
curl https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/10 \
-X POST \
-H "OCS-APIRequest:true" \
-H "X-NC-E2EE-COUNTER:<incremented-counter-from-the-metadata>
```

Retry:

`curl -X POST https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/<file-id> -H "OCS-APIRequest:true"` -d e2e-token="<e2e-token-from-previous-try>"
curl https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/10 \
-X POST \
-H "OCS-APIRequest:true" \
-d "e2e-token:<e2e-token-from-previous-try> \
-H "X-NC-E2EE-COUNTER:<incremented-counter-from-the-metadata>
```

## Unlock file

Expand Down Expand Up @@ -376,12 +388,25 @@ DELETE: `<base-url>/lock/<file-id>`
</ocs>
````


**Example curl call:**

First try:
Unlock:

````shell
curl https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/10 \
-X DELETE \
-H "OCS-APIRequest:true" \
-H "e2e-token:<e2e-token-received-during-lock-operation>
```

`curl -X DELETE https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/10 -H "OCS-APIRequest:true" -H "e2e-token:<e2e-token-received-during-lock-operation>`
Unlock and drop pending changes:

````shell
curl https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/lock/10?abort=true \
-X DELETE \
-H "OCS-APIRequest:true" \
-H "e2e-token:<e2e-token-received-during-lock-operation>
```

## Store meta-data file

Expand Down Expand Up @@ -419,7 +444,13 @@ metaData: content of the encrypted meta-data file

**Example curl call:**

`curl -X POST https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id> -H "OCS-APIRequest:true"` -d metaData="<encrypted-meta-data>"
```bash
curl "https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id>" \
-X POST \
-H "OCS-APIRequest:true" \
-H "e2e-token:<e2e-token-received-during-lock-operation>" \
-d metaData="<encrypted-meta-data>"
```

## Get meta-data file

Expand Down Expand Up @@ -466,8 +497,8 @@ e2e-token: token to authenticate that you are the client who currently manipulat

200 ok: meta data successfully updated

404 not found: if the meta-data file doesn't exist or if the user can't access
the file with the given file-id
404 not found: if the meta-data file doesn't exist or if the user can't access
the file with the given file-id

403 forbidden: if the file was not locked or the client sends the wrong e2e-token

Expand All @@ -491,7 +522,14 @@ the file with the given file-id

**Example curl call:**

`curl -X PUT https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id> -H "OCS-APIRequest:true"` -d "metaData=<encrypted-meta-data>&e2e-token=<e2e-token-received-during-lock-operation>"
```bash
curl "https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id>" \
-X PUT \
-H "OCS-APIRequest:true" \
-H "e2e-token:<e2e-token-received-during-lock-operation>" \
-H "X-NC-E2EE-SIGNATURE:<metadata-signature>" \
-d metaData="<encrypted-meta-data>"
```

## Update filedrop property of meta-data file

Expand All @@ -506,8 +544,8 @@ e2e-token: token to authenticate that you are the client who currently manipulat

200 ok: filedrop successfully updated

404 not found: if the meta-data file doesn't exist or if the user can't access
the file with the given file-id
404 not found: if the meta-data file doesn't exist or if the user can't access
the file with the given file-id

403 forbidden: if the file was not locked or the client sends the wrong e2e-token

Expand Down Expand Up @@ -564,12 +602,16 @@ DELETE: `<base-url>/meta-data/<file-id>`

**Example curl call:**

`curl -X DELETE https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id> -H "OCS-APIRequest:true"`

```bash
curl "https://<user>:<password>@<nextcloud>/ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/<file-id>" \
-X DELETE \
-H "OCS-APIRequest:true" \
-H "e2e-token:<e2e-token-received-during-lock-operation>"
```

## Get server public key

This is the key, used to sign the users public keys. By retrieving the server's
This is the key, used to sign the users public keys. By retrieving the server's
public key the clients can check the signature of the users public keys.

GET: `<base-url>/server-key`
Expand Down
4 changes: 2 additions & 2 deletions js/end_to_end_encryption-filedrop.js

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions js/end_to_end_encryption-filedrop.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ PERFORMANCE OF THIS SOFTWARE.

/*! @license DOMPurify 2.4.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.4/LICENSE */

/*! For license information please see NcAppContent.js.LICENSE.txt */

/*! For license information please see NcContent.js.LICENSE.txt */

/*! Hammer.JS - v2.0.7 - 2016-04-22
* http://hammerjs.github.io/
*
Expand Down
2 changes: 1 addition & 1 deletion js/end_to_end_encryption-filedrop.js.map

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@
use OCA\EndToEndEncryption\EncryptionManager;
use OCA\EndToEndEncryption\IKeyStorage;
use OCA\EndToEndEncryption\IMetaDataStorage;
use OCA\EndToEndEncryption\IMetaDataStorageV1;
use OCA\EndToEndEncryption\KeyStorage;
use OCA\EndToEndEncryption\Listener\UserDeletedListener;
use OCA\EndToEndEncryption\MetaDataStorage;
use OCA\EndToEndEncryption\MetaDataStorageV1;
use OCA\EndToEndEncryption\Middleware\CanUseAppMiddleware;
use OCA\EndToEndEncryption\Middleware\ClientHasCapabilityMiddleware;
use OCA\EndToEndEncryption\Middleware\UserAgentCheckMiddleware;
use OCA\Files_Trashbin\Events\MoveToTrashEvent;
use OCA\Files_Versions\Events\CreateVersionEvent;
Expand Down Expand Up @@ -66,7 +69,9 @@ public function register(IRegistrationContext $context): void {
$context->registerCapability(Capabilities::class);
$context->registerMiddleware(UserAgentCheckMiddleware::class);
$context->registerMiddleware(CanUseAppMiddleware::class);
$context->registerMiddleware(ClientHasCapabilityMiddleware::class);
$context->registerServiceAlias(IKeyStorage::class, KeyStorage::class);
$context->registerServiceAlias(IMetaDataStorageV1::class, MetaDataStorageV1::class);
$context->registerServiceAlias(IMetaDataStorage::class, MetaDataStorage::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerPublicShareTemplateProvider(E2EEPublicShareTemplateProvider::class);
Expand Down
2 changes: 1 addition & 1 deletion lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function getCapabilities(): array {
$capabilities = ['end-to-end-encryption' =>
[
'enabled' => true,
'api-version' => '1.2',
'api-version' => '2.0',
'keys-exist' => $keysExist,
]
];
Expand Down
Loading