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
11ba4b5
Create v2 routes
Altahrim Aug 16, 2023
a8b9f84
Wrap-up changes for updated subfolders
artonge Mar 20, 2023
cfa1c25
Use header to provide e2e-token
artonge May 23, 2023
0136ba4
Use major.minor for api-versions in capabilities
artonge May 23, 2023
3e650b8
Run psalm:fix
artonge May 23, 2023
40fcf73
Update API doc
artonge May 23, 2023
6809689
Prevent access to set and delete endpoints without valid lock token
artonge May 24, 2023
9184afe
Allow to abort changes during unlock
artonge Jun 1, 2023
1832289
Add support for X-NC-E2EE-COUNTER
artonge Jun 1, 2023
c113866
Store signature on metadata save
artonge Jul 3, 2023
f7cf8cc
Check if required headers are set
artonge Jul 5, 2023
9a20a39
Update api.md for new headers
artonge Jul 17, 2023
787b1c2
REMOVE ME: temporary fix to allow both routes on same endpoint
Altahrim Aug 24, 2023
7b17847
Fix leave share for root folder
Altahrim Aug 30, 2023
93734bf
Adapt filedrop to v2 routes
artonge Aug 31, 2023
ac78ddd
Adapt filedrop to v2
artonge Jan 8, 2024
861ce18
Add default mimetype
artonge Jan 11, 2024
ed8e83e
Remove triple base64 encoding
artonge Jan 11, 2024
3b87088
Use top e2ee folder to retrieve users list in public shares
artonge Jan 15, 2024
1d62c07
Correctly validate lock state
artonge Jan 16, 2024
9463aad
Run cs:fix
artonge Jan 16, 2024
cd7c4bd
Fix psalm errors
artonge Jan 16, 2024
8f25f61
Fix lint error
artonge Jan 16, 2024
c151738
Fix phpUnit tests
artonge Jan 16, 2024
a183add
Fix eslint error
artonge Jan 17, 2024
0e06e46
Fix php unit tests
artonge Jan 17, 2024
daa6e6d
Expose all routes to v2
artonge Jan 17, 2024
2600192
Move folder lock to the backend for filedrops
artonge Jan 18, 2024
b047110
Add node workflows
artonge Jan 18, 2024
4ad7837
Fix phpunit tests
artonge Jan 18, 2024
1b7218b
Ignore missing signature on v2 endpoint when the metadata is not in v2
artonge Jan 23, 2024
a32f989
Return 403 when old client access version 2.0 encrypted folders
artonge Jan 25, 2024
b8b1211
Improve readability of isLocked return condition
artonge Jan 31, 2024
14df4e7
Remove support for e2e-token in header in PUT v1/meta-data
artonge Jan 31, 2024
89eb51b
Apply review suggestions
artonge Jan 31, 2024
b1892d4
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