Skip to content

Commit

Permalink
Merge pull request #2942 from nextcloud/fix-encryption-wrapper-not-se…
Browse files Browse the repository at this point in the history
…en-by-groupfolder-cache

Fix encryption wrapper not seen by groupfolder cache
  • Loading branch information
come-nc authored Aug 22, 2024
2 parents f76dc22 + f56662d commit a0a34e5
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 4 deletions.
169 changes: 169 additions & 0 deletions cypress/e2e/encryption.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import {
addUserToGroup,
createGroup,
createGroupFolder,
deleteGroupFolder,
disableEncryption,
disableEncryptionModule,
disableGroupfoldersEncryption,
disableHomeStorageEncryption,
enableEncryption,
enableEncryptionModule,
enableGroupfoldersEncryption,
enableHomeStorageEncryption,
enterFolder,
fileOrFolderExists,
PERMISSION_DELETE,
PERMISSION_READ,
PERMISSION_WRITE,
} from './groupfoldersUtils'

import {
assertFileContent,
moveFile,
} from './files/filesUtils'

import { randHash } from '../utils'

import type { User } from '@nextcloud/cypress'

describe('Groupfolders encryption behavior', () => {
let user1: User
let groupFolderId: string
let groupName: string
let groupFolderName: string

before(() => {
enableEncryptionModule()
enableEncryption()
})

beforeEach(() => {
if (groupFolderId) {
deleteGroupFolder(groupFolderId)
}
groupName = `test_group_${randHash()}`
groupFolderName = `test_group_folder_${randHash()}`

cy.createRandomUser()
.then(_user => {
user1 = _user
})
createGroup(groupName)
.then(() => {
addUserToGroup(groupName, user1.userId)
createGroupFolder(groupFolderName, groupName, [PERMISSION_READ, PERMISSION_WRITE, PERMISSION_DELETE])
})
})

after(() => {
// Restore default values
disableGroupfoldersEncryption()
enableHomeStorageEncryption()
disableEncryption()
disableEncryptionModule()
})

it('Move file from encrypted storage to encrypted groupfolder', () => {
enableHomeStorageEncryption()
enableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', '/file1.txt')

cy.login(user1)
cy.visit('/apps/files')

moveFile('file1.txt', groupFolderName)

enterFolder(groupFolderName)
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})

it('Move file from encrypted storage to non encrypted groupfolder', () => {
enableHomeStorageEncryption()
disableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', '/file1.txt')

cy.login(user1)
cy.visit('/apps/files')

moveFile('file1.txt', groupFolderName)

enterFolder(groupFolderName)
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})

it('Move file from non encrypted storage to encrypted groupfolder', () => {
disableHomeStorageEncryption()
enableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', '/file1.txt')

cy.login(user1)
cy.visit('/apps/files')

moveFile('file1.txt', groupFolderName)

enterFolder(groupFolderName)
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})

it('Move file from encrypted groupfolder to encrypted storage', () => {
enableHomeStorageEncryption()
enableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', `/${groupFolderName}/file1.txt`)

cy.login(user1)
cy.visit('/apps/files')

enterFolder(groupFolderName)
moveFile('file1.txt', '/')

cy.visit('/apps/files')
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})

it('Move file from encrypted groupfolder to non encrypted storage', () => {
disableHomeStorageEncryption()
enableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', `/${groupFolderName}/file1.txt`)

cy.login(user1)
cy.visit('/apps/files')

enterFolder(groupFolderName)
moveFile('file1.txt', '/')

cy.visit('/apps/files')
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})

it('Move file from non encrypted groupfolder to encrypted storage', () => {
enableHomeStorageEncryption()
disableGroupfoldersEncryption()

cy.uploadContent(user1, new Blob(['Content of the file']), 'text/plain', `/${groupFolderName}/file1.txt`)

cy.login(user1)
cy.visit('/apps/files')

enterFolder(groupFolderName)
moveFile('file1.txt', '/')

cy.visit('/apps/files')
fileOrFolderExists('file1.txt')
assertFileContent('file1.txt', 'Content of the file')
})
})
8 changes: 8 additions & 0 deletions cypress/e2e/files/filesUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,11 @@ export const clickOnBreadcumbs = (label: string) => {
cy.get('[data-cy-files-content-breadcrumbs]').contains(label).click()
cy.wait('@propfind')
}

export const assertFileContent = (fileName: string, expectedContent: string) => {
cy.intercept({ method: 'GET', times: 1, url: 'remote.php/**' }).as('downloadFile')
getRowForFile(fileName).should('be.visible')
triggerActionForFile(fileName, 'download')
cy.wait('@downloadFile')
.then(({ response }) => expect(response?.body).to.equal(expectedContent))
}
33 changes: 33 additions & 0 deletions cypress/e2e/groupfoldersUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,39 @@ export function deleteGroupFolder(groupFolderId: string) {
return cy.runOccCommand(`groupfolders:delete ${groupFolderId}`)
}

export function enableEncryptionModule() {
return cy.runOccCommand('app:enable encryption')
}

export function disableEncryptionModule() {
return cy.runOccCommand('app:disable encryption')
}

export function enableEncryption() {
return cy.runOccCommand('config:app:set --value=yes core encryption_enabled')
}

export function disableEncryption() {
return cy.runOccCommand('config:app:delete core encryption_enabled')
}

export function enableHomeStorageEncryption() {
// Default value is enabled
return cy.runOccCommand('config:app:delete encryption encryptHomeStorage')
}

export function disableHomeStorageEncryption() {
return cy.runOccCommand('config:app:set --value=0 encryption encryptHomeStorage')
}

export function enableGroupfoldersEncryption() {
return cy.runOccCommand('config:app:set --value=true groupfolders enable_encryption')
}

export function disableGroupfoldersEncryption() {
return cy.runOccCommand('config:app:delete groupfolders enable_encryption')
}

export function fileOrFolderExists(name: string) {
// Make sure file list is loaded first
cy.get('[data-cy-files-list-tfoot],[data-cy-files-content-empty]').should('be.visible')
Expand Down
29 changes: 29 additions & 0 deletions lib/Mount/GroupFolderEncryptionJail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\GroupFolders\Mount;

use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Storage\Wrapper\Jail;

/**
* Jail with overridden behaviors specific to group folders when encryption is
* enabled.
*/
class GroupFolderEncryptionJail extends Jail {
public function getCache($path = '', $storage = null) {
if (!$storage) {
$storage = $this->getWrapperStorage();
}
// By default the Jail reuses the inner cache, but when encryption is
// enabled the storage needs to be passed to the cache so it takes into
// account the outer Encryption wrapper.
$sourceCache = $this->getWrapperStorage()->getCache($this->getUnjailedPath($path), $storage);
return new CacheJail($sourceCache, $this->rootPath);
}
}
12 changes: 8 additions & 4 deletions lib/Mount/MountProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,11 @@ public function getMount(
$cacheEntry['permissions'] &= $aclRootPermissions;
}

$baseStorage = new Jail([
'storage' => $storage,
'root' => $rootPath
]);
if ($this->enableEncryption) {
$baseStorage = new GroupFolderEncryptionJail([
'storage' => $storage,
'root' => $rootPath
]);
$quotaStorage = new GroupFolderStorage([
'storage' => $baseStorage,
'quota' => $quota,
Expand All @@ -231,6 +231,10 @@ public function getMount(
'mountOwner' => $user,
]);
} else {
$baseStorage = new Jail([
'storage' => $storage,
'root' => $rootPath
]);
$quotaStorage = new GroupFolderNoEncryptionStorage([
'storage' => $baseStorage,
'quota' => $quota,
Expand Down
6 changes: 6 additions & 0 deletions tests/stub.phpstub
Original file line number Diff line number Diff line change
Expand Up @@ -750,9 +750,15 @@ namespace OC\Files\Cache {

namespace OC\Files\Cache\Wrapper {
use OC\Files\Cache\Cache;
use OCP\Files\Cache\ICache;

class CacheWrapper extends Cache {
public function getCache(): Cache {}
}

class CacheJail extends CacheWrapper {
public function __construct(?ICache $cache, string $root, ?CacheDependencies $dependencies = null) {}
}
}

namespace OC\Files {
Expand Down

0 comments on commit a0a34e5

Please sign in to comment.