diff --git a/cypress/e2e/files_external/StorageUtils.ts b/cypress/e2e/files_external/StorageUtils.ts index 0f7fec65edf..33402feac1f 100644 --- a/cypress/e2e/files_external/StorageUtils.ts +++ b/cypress/e2e/files_external/StorageUtils.ts @@ -9,10 +9,15 @@ export type StorageConfig = { [key: string]: string } +export type StorageMountOption = { + readonly: boolean +} + export enum StorageBackend { DAV = 'dav', SMB = 'smb', SFTP = 'sftp', + LOCAL = 'local', } export enum AuthBackend { @@ -22,6 +27,7 @@ export enum AuthBackend { SessionCredentials = 'password::sessioncredentials', UserGlobalAuth = 'password::global::user', UserProvided = 'password::userprovided', + Null = 'null::null', } /** @@ -35,4 +41,20 @@ export function createStorageWithConfig(mountPoint: string, storageBackend: Stor cy.log(`Creating storage with command: ${command}`) return cy.runOccCommand(command) + .then(({ stdout }) => { + return stdout.replace('Storage created with id ', '') + }) +} + +export function setStorageMountOptions(mountId: string, options: StorageMountOption) { + for (const [key, value] of Object.entries(options)) { + cy.runOccCommand(`files_external:option ${mountId} ${key} ${value}`) + } +} + +export function deleteAllExternalStorages() { + cy.runOccCommand('files_external:list --all --output=json').then(({ stdout }) => { + const list = JSON.parse(stdout) + list.forEach((storage) => cy.runOccCommand(`files_external:delete --yes ${storage.mount_id}`), { failOnNonZeroExit: false }) + }) } diff --git a/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts b/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts new file mode 100644 index 00000000000..b2938e3106b --- /dev/null +++ b/cypress/e2e/files_external/home-folder-root-mount-permissions.cy.ts @@ -0,0 +1,46 @@ +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { User } from '@nextcloud/cypress' +import { AuthBackend, createStorageWithConfig, deleteAllExternalStorages, setStorageMountOptions, StorageBackend } from './StorageUtils' + +describe('Home folder root mount permissions', { testIsolation: true }, () => { + let user1: User + + before(() => { + cy.runOccCommand('app:enable files_external') + cy.createRandomUser().then((user) => { user1 = user }) + }) + + after(() => { + deleteAllExternalStorages() + cy.runOccCommand('app:disable files_external') + }) + + it('Does not show write actions on read-only storage mounted at the root of the user\'s home folder', () => { + cy.login(user1) + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders --default-value=[]') + .then(({ stdout }) => assert.equal(stdout.trim(), '[]')) + + cy.get('[data-cy-upload-picker=""]').should('exist') + + createStorageWithConfig('/', StorageBackend.LOCAL, AuthBackend.Null, { datadir: '/tmp' }) + .then((id) => setStorageMountOptions(id, { readonly: true })) + // HACK: somehow, we need to create an external folder targeting a subpath for the previous one to show. + createStorageWithConfig('/a', StorageBackend.LOCAL, AuthBackend.Null, { datadir: '/tmp' }) + cy.visit('/apps/files/') + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders') + .then(({ stdout }) => assert.equal(stdout.trim(), '["files_external"]')) + cy.get('[data-cy-upload-picker=""]').should('not.exist') + + deleteAllExternalStorages() + cy.visit('/apps/files/') + cy.runOccCommand('config:app:get files overwrites_home_folders') + .then(({ stdout }) => assert.equal(stdout.trim(), '[]')) + cy.get('[data-cy-upload-picker=""]').should('exist') + }) +})