diff options
-rw-r--r-- | __mocks__/@nextcloud/axios.ts | 1 | ||||
-rw-r--r-- | apps/files_sharing/lib/AppInfo/Application.php | 9 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareAPIController.php | 6 | ||||
-rw-r--r-- | apps/files_sharing/lib/Listener/LoadAdditionalListener.php | 6 | ||||
-rw-r--r-- | apps/files_sharing/src/services/SharingService.spec.ts | 364 | ||||
-rw-r--r-- | apps/files_sharing/src/services/SharingService.ts | 45 | ||||
-rw-r--r-- | apps/files_sharing/src/views/shares.spec.ts | 125 | ||||
-rw-r--r-- | apps/files_sharing/src/views/shares.ts | 14 | ||||
-rw-r--r-- | apps/files_sharing/tests/Controller/ShareAPIControllerTest.php | 120 | ||||
-rw-r--r-- | apps/files_sharing/tests/js/appSpec.js | 125 | ||||
-rw-r--r-- | build/integration/sharing_features/sharing-v1-part4.feature | 41 |
11 files changed, 657 insertions, 199 deletions
diff --git a/__mocks__/@nextcloud/axios.ts b/__mocks__/@nextcloud/axios.ts index 02564ab6c6d..e9a440f4747 100644 --- a/__mocks__/@nextcloud/axios.ts +++ b/__mocks__/@nextcloud/axios.ts @@ -20,6 +20,7 @@ * */ export default { + get: async () => ({ status: 200, data: {} }), delete: async () => ({ status: 200, data: {} }), post: async () => ({ status: 200, data: {} }), } diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index 649f5d0f78f..946d82a3df7 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -117,7 +117,6 @@ class Application extends App implements IBootstrap { $context->injectFn([$this, 'registerMountProviders']); $context->injectFn([$this, 'registerEventsScripts']); $context->injectFn([$this, 'registerDownloadEvents']); - $context->injectFn([$this, 'loadFilesSharing']); Helper::registerHooks(); @@ -214,12 +213,4 @@ class Application extends App implements IBootstrap { } ); } - - public function loadFilesSharing(IManager $shareManager): void { - if (!$shareManager->shareApiEnabled() || !class_exists('\OCA\Files\App')) { - return; - } - - Util::addScript(self::APP_ID, 'files_sharing', 'files'); - } } diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index e80412f18b4..5d5015cfca6 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -232,7 +232,7 @@ class ShareAPIController extends OCSController { // Get the original node permission if the share owner is the current user if ($isOwnShare) { - $result['permissions'] = $node->getPermissions(); + $result['item_permissions'] = $node->getPermissions(); } $result['mimetype'] = $node->getMimetype(); @@ -243,8 +243,8 @@ class ShareAPIController extends OCSController { $result['file_source'] = $node->getId(); $result['file_parent'] = $node->getParent()->getId(); $result['file_target'] = $share->getTarget(); - $result['size'] = $node->getSize(); - $result['mtime'] = $node->getMTime(); + $result['item_size'] = $node->getSize(); + $result['item_mtime'] = $node->getMTime(); $expiration = $share->getExpirationDate(); if ($expiration !== null) { diff --git a/apps/files_sharing/lib/Listener/LoadAdditionalListener.php b/apps/files_sharing/lib/Listener/LoadAdditionalListener.php index d44b8c559ad..583cd575793 100644 --- a/apps/files_sharing/lib/Listener/LoadAdditionalListener.php +++ b/apps/files_sharing/lib/Listener/LoadAdditionalListener.php @@ -29,6 +29,7 @@ use OCA\Files_Sharing\AppInfo\Application; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\Share\IManager; use OCP\Util; class LoadAdditionalListener implements IEventListener { @@ -40,5 +41,10 @@ class LoadAdditionalListener implements IEventListener { // After files for the breadcrumb share indicator Util::addScript(Application::APP_ID, 'additionalScripts', 'files'); Util::addStyle(Application::APP_ID, 'icons'); + + $shareManager = \OC::$server->get(IManager::class); + if ($shareManager->shareApiEnabled() && class_exists('\OCA\Files\App')) { + Util::addScript(Application::APP_ID, 'files_sharing', 'files'); + } } } diff --git a/apps/files_sharing/src/services/SharingService.spec.ts b/apps/files_sharing/src/services/SharingService.spec.ts new file mode 100644 index 00000000000..a3269ac7180 --- /dev/null +++ b/apps/files_sharing/src/services/SharingService.spec.ts @@ -0,0 +1,364 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +import { expect } from '@jest/globals' +import axios from '@nextcloud/axios' +import { Type } from '@nextcloud/sharing' +import * as auth from '@nextcloud/auth' + +import { getContents, type OCSResponse } from './SharingService' +import { File, Folder } from '@nextcloud/files' +import logger from './logger' + +global.window.OC = { + TAG_FAVORITE: '_$!<Favorite>!$_', +} + +describe('SharingService methods definitions', () => { + beforeAll(() => { + jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + return { + data: { + ocs: { + meta: { + status: 'ok', + statuscode: 200, + message: 'OK', + }, + data: [], + }, + } as OCSResponse, + } + }) + }) + + afterAll(() => { + jest.restoreAllMocks() + }) + + test('Shared with you', async () => { + await getContents(true, false, false, false, []) + + expect(axios.get).toHaveBeenCalledTimes(2) + expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + shared_with_me: true, + include_tags: true, + }, + }) + expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + include_tags: true, + }, + }) + }) + + test('Shared with others', async () => { + await getContents(false, true, false, false, []) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + shared_with_me: false, + include_tags: true, + }, + }) + }) + + test('Pending shares', async () => { + await getContents(false, false, true, false, []) + + expect(axios.get).toHaveBeenCalledTimes(2) + expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares/pending', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + include_tags: true, + }, + }) + expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + include_tags: true, + }, + }) + }) + + test('Deleted shares', async () => { + await getContents(false, true, false, false, []) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(axios.get).toHaveBeenCalledWith('http://localhost/ocs/v2.php/apps/files_sharing/api/v1/shares', { + headers: { + 'Content-Type': 'application/json', + }, + params: { + shared_with_me: false, + include_tags: true, + }, + }) + }) + + test('Unknown owner', async () => { + jest.spyOn(auth, 'getCurrentUser').mockReturnValue(null) + const results = await getContents(false, true, false, false, []) + + expect(results.folder.owner).toEqual(null) + }) +}) + +describe('SharingService filtering', () => { + beforeAll(() => { + jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + return { + data: { + ocs: { + meta: { + status: 'ok', + statuscode: 200, + message: 'OK', + }, + data: [ + { + id: '62', + share_type: Type.SHARE_TYPE_USER, + uid_owner: 'test', + displayname_owner: 'test', + permissions: 31, + stime: 1688666292, + expiration: '2023-07-13 00:00:00', + token: null, + path: '/Collaborators', + item_type: 'folder', + item_permissions: 31, + mimetype: 'httpd/unix-directory', + storage: 224, + item_source: 419413, + file_source: 419413, + file_parent: 419336, + file_target: '/Collaborators', + item_size: 41434, + item_mtime: 1688662980, + }, + ], + }, + }, + } + }) + }) + + afterAll(() => { + jest.restoreAllMocks() + }) + + test('Shared with others filtering', async () => { + const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_USER]) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(shares.contents).toHaveLength(1) + expect(shares.contents[0].fileid).toBe(419413) + expect(shares.contents[0]).toBeInstanceOf(Folder) + }) + + test('Shared with others filtering empty', async () => { + const shares = await getContents(false, true, false, false, [Type.SHARE_TYPE_LINK]) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(shares.contents).toHaveLength(0) + }) +}) + +describe('SharingService share to Node mapping', () => { + const shareFile = { + id: '66', + share_type: 0, + uid_owner: 'test', + displayname_owner: 'test', + permissions: 19, + can_edit: true, + can_delete: true, + stime: 1688721609, + parent: null, + expiration: '2023-07-14 00:00:00', + token: null, + uid_file_owner: 'test', + note: '', + label: null, + displayname_file_owner: 'test', + path: '/document.md', + item_type: 'file', + item_permissions: 27, + mimetype: 'text/markdown', + has_preview: true, + storage_id: 'home::test', + storage: 224, + item_source: 530936, + file_source: 530936, + file_parent: 419336, + file_target: '/document.md', + item_size: 123, + item_mtime: 1688721600, + share_with: 'user00', + share_with_displayname: 'User00', + share_with_displayname_unique: 'user00@domain.com', + status: { + status: 'away', + message: null, + icon: null, + clearAt: null, + }, + mail_send: 0, + hide_download: 0, + attributes: null, + tags: [], + } + + const shareFolder = { + id: '67', + share_type: 0, + uid_owner: 'test', + displayname_owner: 'test', + permissions: 31, + can_edit: true, + can_delete: true, + stime: 1688721629, + parent: null, + expiration: '2023-07-14 00:00:00', + token: null, + uid_file_owner: 'test', + note: '', + label: null, + displayname_file_owner: 'test', + path: '/Folder', + item_type: 'folder', + item_permissions: 31, + mimetype: 'httpd/unix-directory', + has_preview: false, + storage_id: 'home::test', + storage: 224, + item_source: 531080, + file_source: 531080, + file_parent: 419336, + file_target: '/Folder', + item_size: 0, + item_mtime: 1688721623, + share_with: 'user00', + share_with_displayname: 'User00', + share_with_displayname_unique: 'user00@domain.com', + status: { + status: 'away', + message: null, + icon: null, + clearAt: null, + }, + mail_send: 0, + hide_download: 0, + attributes: null, + tags: [window.OC.TAG_FAVORITE], + } + + test('File', async () => { + jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + data: { + ocs: { + data: [shareFile], + }, + }, + })) + + const shares = await getContents(false, true, false, false) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(shares.contents).toHaveLength(1) + + const file = shares.contents[0] as File + expect(file).toBeInstanceOf(File) + expect(file.fileid).toBe(530936) + expect(file.source).toBe('http://localhost/remote.php/dav/files/test/document.md') + expect(file.owner).toBe('test') + expect(file.mime).toBe('text/markdown') + expect(file.mtime).toBeInstanceOf(Date) + expect(file.size).toBe(123) + expect(file.permissions).toBe(27) + expect(file.root).toBe('/files/test') + expect(file.attributes).toBeInstanceOf(Object) + expect(file.attributes['has-preview']).toBe(true) + expect(file.attributes.previewUrl).toBe('/index.php/core/preview?fileId=530936&x=32&y=32&forceIcon=0') + expect(file.attributes.favorite).toBe(0) + }) + + test('Folder', async () => { + jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + data: { + ocs: { + data: [shareFolder], + }, + }, + })) + + const shares = await getContents(false, true, false, false) + + expect(axios.get).toHaveBeenCalledTimes(1) + expect(shares.contents).toHaveLength(1) + + const folder = shares.contents[0] as Folder + expect(folder).toBeInstanceOf(Folder) + expect(folder.fileid).toBe(531080) + expect(folder.source).toBe('http://localhost/remote.php/dav/files/test/Folder') + expect(folder.owner).toBe('test') + expect(folder.mime).toBe('httpd/unix-directory') + expect(folder.mtime).toBeInstanceOf(Date) + expect(folder.size).toBe(0) + expect(folder.permissions).toBe(31) + expect(folder.root).toBe('/files/test') + expect(folder.attributes).toBeInstanceOf(Object) + expect(folder.attributes['has-preview']).toBe(false) + expect(folder.attributes.previewUrl).toBeUndefined() + expect(folder.attributes.favorite).toBe(1) + }) + + test('Error', async () => { + jest.spyOn(logger, 'error').mockImplementationOnce(() => {}) + jest.spyOn(axios, 'get').mockReturnValueOnce(Promise.resolve({ + data: { + ocs: { + data: [{}], + }, + }, + })) + + const shares = await getContents(false, true, false, false) + expect(shares.contents).toHaveLength(0) + expect(logger.error).toHaveBeenCalledTimes(1) + }) +}) diff --git a/apps/files_sharing/src/services/SharingService.ts b/apps/files_sharing/src/services/SharingService.ts index 036eae07bce..13f7334bbb6 100644 --- a/apps/files_sharing/src/services/SharingService.ts +++ b/apps/files_sharing/src/services/SharingService.ts @@ -26,11 +26,12 @@ import type { ContentsWithRoot } from '../../../files/src/services/Navigation' import { Folder, File } from '@nextcloud/files' import { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router' import { getCurrentUser } from '@nextcloud/auth' -import { rootPath } from '../../../files/src/services/WebdavClient' import axios from '@nextcloud/axios' import logger from './logger' -type OCSResponse = { +export const rootPath = `/files/${getCurrentUser()?.uid}` + +export type OCSResponse = { ocs: { meta: { status: string @@ -47,19 +48,20 @@ const headers = { const ocsEntryToNode = function(ocsEntry: any): Folder | File | null { try { - const Node = ocsEntry?.item_type === 'folder' ? Folder : File + const isFolder = ocsEntry?.item_type === 'folder' + const hasPreview = ocsEntry?.has_preview === true + const Node = isFolder ? Folder : File - // Sometimes it's an int, sometimes it contains the identifier like "ocinternal:123" const fileid = ocsEntry.file_source - const previewUrl = generateUrl('/core/preview?fileId={fileid}&x=32&y=32&forceIcon=0', { fileid }) + const previewUrl = hasPreview ? generateUrl('/core/preview?fileId={fileid}&x=32&y=32&forceIcon=0', { fileid }) : undefined // Generate path and strip double slashes const path = ocsEntry?.path || ocsEntry.file_target - const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replace(/\/\//, '/')) + const source = generateRemoteUrl(`dav/${rootPath}/${path}`.replaceAll(/\/\//gm, '/')) - // Prefer share time if more recent than mtime - let mtime = ocsEntry?.mtime ? new Date((ocsEntry.mtime) * 1000) : undefined - if (ocsEntry?.stime > (ocsEntry?.mtime || 0)) { + // Prefer share time if more recent than item mtime + let mtime = ocsEntry?.item_mtime ? new Date((ocsEntry.item_mtime) * 1000) : undefined + if (ocsEntry?.stime > (ocsEntry?.item_mtime || 0)) { mtime = new Date((ocsEntry.stime) * 1000) } @@ -69,12 +71,13 @@ const ocsEntryToNode = function(ocsEntry: any): Folder | File | null { owner: ocsEntry?.uid_owner, mime: ocsEntry?.mimetype, mtime, - size: ocsEntry?.size || undefined, - permissions: ocsEntry?.permissions, + size: ocsEntry?.item_size, + permissions: ocsEntry?.item_permissions || ocsEntry?.permissions, root: rootPath, attributes: { ...ocsEntry, previewUrl, + 'has-preview': hasPreview, favorite: ocsEntry?.tags?.includes(window.OC.TAG_FAVORITE) ? 1 : 0, }, }) @@ -86,8 +89,7 @@ const ocsEntryToNode = function(ocsEntry: any): Folder | File | null { const getShares = function(shared_with_me = false): AxiosPromise<OCSResponse> { const url = generateOcsUrl('apps/files_sharing/api/v1/shares') - return axios({ - url, + return axios.get(url, { headers, params: { shared_with_me, @@ -101,13 +103,12 @@ const getSharedWithYou = function(): AxiosPromise<OCSResponse> { } const getSharedWithOthers = function(): AxiosPromise<OCSResponse> { - return getShares(false) + return getShares() } const getRemoteShares = function(): AxiosPromise<OCSResponse> { const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares') - return axios({ - url, + return axios.get(url, { headers, params: { include_tags: true, @@ -117,8 +118,7 @@ const getRemoteShares = function(): AxiosPromise<OCSResponse> { const getPendingShares = function(): AxiosPromise<OCSResponse> { const url = generateOcsUrl('apps/files_sharing/api/v1/shares/pending') - return axios({ - url, + return axios.get(url, { headers, params: { include_tags: true, @@ -128,8 +128,7 @@ const getPendingShares = function(): AxiosPromise<OCSResponse> { const getRemotePendingShares = function(): AxiosPromise<OCSResponse> { const url = generateOcsUrl('apps/files_sharing/api/v1/remote_shares/pending') - return axios({ - url, + return axios.get(url, { headers, params: { include_tags: true, @@ -139,8 +138,7 @@ const getRemotePendingShares = function(): AxiosPromise<OCSResponse> { const getDeletedShares = function(): AxiosPromise<OCSResponse> { const url = generateOcsUrl('apps/files_sharing/api/v1/deletedshares') - return axios({ - url, + return axios.get(url, { headers, params: { include_tags: true, @@ -176,8 +174,9 @@ export const getContents = async (sharedWithYou = true, sharedWithOthers = true, folder: new Folder({ id: 0, source: generateRemoteUrl('dav' + rootPath), - owner: getCurrentUser()?.uid || '', + owner: getCurrentUser()?.uid || null, }), contents, } } + diff --git a/apps/files_sharing/src/views/shares.spec.ts b/apps/files_sharing/src/views/shares.spec.ts new file mode 100644 index 00000000000..353e82b6f84 --- /dev/null +++ b/apps/files_sharing/src/views/shares.spec.ts @@ -0,0 +1,125 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +/* eslint-disable n/no-extraneous-import */ +import { expect } from '@jest/globals' +import axios from '@nextcloud/axios' + +import { type Navigation } from '../../../files/src/services/Navigation' +import { type OCSResponse } from '../services/SharingService' +import NavigationService from '../../../files/src/services/Navigation' +import registerSharingViews from './shares' + +import '../main' +import { Folder } from '@nextcloud/files' + +describe('Sharing views definition', () => { + let Navigation + beforeEach(() => { + Navigation = new NavigationService() + window.OCP = { Files: { Navigation } } + }) + + afterAll(() => { + delete window.OCP + }) + + test('Default values', () => { + jest.spyOn(Navigation, 'register') + + expect(Navigation.views.length).toBe(0) + + registerSharingViews() + const shareOverviewView = Navigation.views.find(view => view.id === 'shareoverview') as Navigation + const sharesChildViews = Navigation.views.filter(view => view.parent === 'shareoverview') as Navigation[] + + expect(Navigation.register).toHaveBeenCalledTimes(6) + + // one main view and no children + expect(Navigation.views.length).toBe(6) + expect(shareOverviewView).toBeDefined() + expect(sharesChildViews.length).toBe(5) + + expect(shareOverviewView?.id).toBe('shareoverview') + expect(shareOverviewView?.name).toBe('Shares') + expect(shareOverviewView?.caption).toBe('Overview of shared files.') + expect(shareOverviewView?.icon).toBe('<svg>SvgMock</svg>') + expect(shareOverviewView?.order).toBe(20) + expect(shareOverviewView?.columns).toStrictEqual([]) + expect(shareOverviewView?.getContents).toBeDefined() + + const dataProvider = [ + { id: 'sharingin', name: 'Shared with you', caption: 'List of files that are shared with you.' }, + { id: 'sharingout', name: 'Shared with others', caption: 'List of files that you shared with others.' }, + { id: 'sharinglinks', name: 'Shared by link', caption: 'List of files that are shared by link.' }, + { id: 'deletedshares', name: 'Deleted shares', caption: 'List of shares that you removed yourself from.' }, + { id: 'pendingshares', name: 'Pending shares', caption: 'List of unapproved shares.' }, + ] + + sharesChildViews.forEach((view, index) => { + expect(view?.id).toBe(dataProvider[index].id) + expect(view?.parent).toBe('shareoverview') + expect(view?.name).toBe(dataProvider[index].name) + expect(view?.caption).toBe(dataProvider[index].caption) + expect(view?.icon).toBe('<svg>SvgMock</svg>') + expect(view?.order).toBe(index + 1) + expect(view?.columns).toStrictEqual([]) + expect(view?.getContents).toBeDefined() + }) + }) +}) + +describe('Sharing views contents', () => { + let Navigation + beforeEach(() => { + Navigation = new NavigationService() + window.OCP = { Files: { Navigation } } + }) + + afterAll(() => { + delete window.OCP + }) + + test('Sharing overview get contents', async () => { + jest.spyOn(axios, 'get').mockImplementation(async (): Promise<any> => { + return { + data: { + ocs: { + meta: { + status: 'ok', + statuscode: 200, + message: 'OK', + }, + data: [], + }, + } as OCSResponse, + } + }) + + registerSharingViews() + expect(Navigation.views.length).toBe(6) + Navigation.views.forEach(async (view: Navigation) => { + const content = await view.getContents('/') + expect(content.contents).toStrictEqual([]) + expect(content.folder).toBeInstanceOf(Folder) + }) + }) +}) diff --git a/apps/files_sharing/src/views/shares.ts b/apps/files_sharing/src/views/shares.ts index 4afc9c07ef5..1827d6ad54f 100644 --- a/apps/files_sharing/src/views/shares.ts +++ b/apps/files_sharing/src/views/shares.ts @@ -33,8 +33,8 @@ import ShareVariantSvg from '@mdi/svg/svg/share-variant.svg?raw' import { getContents } from '../services/SharingService' export const sharesViewId = 'shareoverview' -export const pendingSharesViewId = 'pendingshares' export const deletedSharesViewId = 'deletedshares' +export const pendingSharesViewId = 'pendingshares' export default () => { const Navigation = window.OCP.Files.Navigation as NavigationService @@ -57,7 +57,7 @@ export default () => { caption: t('files_sharing', 'List of files that are shared with you.'), icon: AccountSvg, - order: 20, + order: 1, parent: sharesViewId, columns: [], @@ -71,7 +71,7 @@ export default () => { caption: t('files_sharing', 'List of files that you shared with others.'), icon: AccountGroupSvg, - order: 20, + order: 2, parent: sharesViewId, columns: [], @@ -82,10 +82,10 @@ export default () => { Navigation.register({ id: 'sharinglinks', name: t('files_sharing', 'Shared by link'), - caption: t('files_sharing', 'List of files that you shared with a share link.'), + caption: t('files_sharing', 'List of files that are shared by link.'), icon: LinkSvg, - order: 20, + order: 3, parent: sharesViewId, columns: [], @@ -99,7 +99,7 @@ export default () => { caption: t('files_sharing', 'List of shares that you removed yourself from.'), icon: DeleteSvg, - order: 20, + order: 4, parent: sharesViewId, columns: [], @@ -113,7 +113,7 @@ export default () => { caption: t('files_sharing', 'List of unapproved shares.'), icon: AccountClockSvg, - order: 20, + order: 5, parent: sharesViewId, columns: [], diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 2a2a7d940be..df63f61606f 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -576,6 +576,8 @@ class ShareAPIControllerTest extends TestCase { $file->method('getPath')->willReturn('file'); $file->method('getStorage')->willReturn($storage); $file->method('getParent')->willReturn($parentFolder); + $file->method('getSize')->willReturn(123465); + $file->method('getMTime')->willReturn(1234567890); $file->method('getMimeType')->willReturn('myMimeType'); $folder = $this->getMockBuilder('OCP\Files\Folder')->getMock(); @@ -583,6 +585,8 @@ class ShareAPIControllerTest extends TestCase { $folder->method('getPath')->willReturn('folder'); $folder->method('getStorage')->willReturn($storage); $folder->method('getParent')->willReturn($parentFolder); + $folder->method('getSize')->willReturn(123465); + $folder->method('getMTime')->willReturn(1234567890); $folder->method('getMimeType')->willReturn('myFolderMimeType'); [$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes(); @@ -637,6 +641,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'status' => [], + 'item_size' => 123465, + 'item_mtime' => 1234567890, 'attributes' => null, ]; $data[] = [$share, $expected]; @@ -689,6 +695,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123465, + 'item_mtime' => 1234567890, 'attributes' => null, ]; $data[] = [$share, $expected]; @@ -747,6 +755,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123465, + 'item_mtime' => 1234567890, 'attributes' => null, ]; $data[] = [$share, $expected]; @@ -3735,6 +3745,13 @@ class ShareAPIControllerTest extends TestCase { $folder->method('getParent')->willReturn($parent); $fileWithPreview->method('getParent')->willReturn($parent); + $file->method('getSize')->willReturn(123456); + $folder->method('getSize')->willReturn(123456); + $fileWithPreview->method('getSize')->willReturn(123456); + $file->method('getMTime')->willReturn(1234567890); + $folder->method('getMTime')->willReturn(1234567890); + $fileWithPreview->method('getMTime')->willReturn(1234567890); + $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock(); $cache->method('getNumericStorageId')->willReturn(100); $storage = $this->createMock(Storage::class); @@ -3772,7 +3789,7 @@ class ShareAPIControllerTest extends TestCase { // User backend down $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_USER, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -3796,7 +3813,7 @@ class ShareAPIControllerTest extends TestCase { 'share_with_displayname' => 'recipient', 'share_with_displayname_unique' => 'recipient', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'mail_send' => 0, 'mimetype' => 'myMimeType', 'has_preview' => false, @@ -3804,13 +3821,15 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'status' => [], + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]', ], $share, [], false ]; // User backend up $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_USER, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiatorDN', @@ -3823,7 +3842,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'ownerDN', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -3842,6 +3861,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'status' => [], + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]', ], $share, [ ['owner', $owner], @@ -3864,7 +3885,7 @@ class ShareAPIControllerTest extends TestCase { // User backend down $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_USER, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -3877,7 +3898,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -3896,6 +3917,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'status' => [], + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -3914,7 +3937,7 @@ class ShareAPIControllerTest extends TestCase { // User backend down $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_USER, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -3927,7 +3950,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'currentUser', 'displayname_file_owner' => 'currentUser', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -3946,6 +3969,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => true, 'can_delete' => true, 'status' => [], + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -3966,7 +3991,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_GROUP, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -3979,7 +4004,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -3996,6 +4021,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4014,7 +4041,7 @@ class ShareAPIControllerTest extends TestCase { ->setId(42); $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_GROUP, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4026,7 +4053,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'file', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -4043,6 +4070,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4064,7 +4093,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_LINK, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4097,6 +4126,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4119,7 +4150,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_LINK, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4151,6 +4182,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4170,7 +4203,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_REMOTE, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4182,7 +4215,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4199,6 +4232,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4218,7 +4253,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_REMOTE_GROUP, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4230,7 +4265,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4247,6 +4282,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4267,7 +4304,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_CIRCLE, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4280,7 +4317,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4298,6 +4335,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4316,7 +4355,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_CIRCLE, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4328,7 +4367,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4346,6 +4385,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4364,7 +4405,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_CIRCLE, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4376,7 +4417,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4394,6 +4435,8 @@ class ShareAPIControllerTest extends TestCase { 'hide_download' => 0, 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4427,7 +4470,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_EMAIL, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4439,7 +4482,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4459,6 +4502,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'password_expiration_time' => null, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4478,7 +4523,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_EMAIL, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4490,7 +4535,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'owner', 'displayname_file_owner' => 'owner', 'note' => '', - 'label' => null, + 'label' => '', 'path' => 'folder', 'item_type' => 'folder', 'storage_id' => 'storageId', @@ -4510,6 +4555,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => false, 'can_delete' => false, 'password_expiration_time' => null, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4529,7 +4576,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_USER, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4541,7 +4588,7 @@ class ShareAPIControllerTest extends TestCase { 'uid_file_owner' => 'currentUser', 'displayname_file_owner' => 'currentUser', 'note' => 'personal note', - 'label' => null, + 'label' => '', 'path' => 'fileWithPreview', 'item_type' => 'file', 'storage_id' => 'storageId', @@ -4560,6 +4607,8 @@ class ShareAPIControllerTest extends TestCase { 'can_edit' => true, 'can_delete' => true, 'status' => [], + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, [], false ]; @@ -4659,6 +4708,9 @@ class ShareAPIControllerTest extends TestCase { $file->method('getParent')->willReturn($parent); + $file->method('getSize')->willReturn(123456); + $file->method('getMTime')->willReturn(1234567890); + $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock(); $cache->method('getNumericStorageId')->willReturn(100); $storage = $this->createMock(Storage::class); @@ -4683,7 +4735,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_ROOM, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4712,6 +4764,8 @@ class ShareAPIControllerTest extends TestCase { 'label' => '', 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, false, [] ]; @@ -4730,7 +4784,7 @@ class ShareAPIControllerTest extends TestCase { $result[] = [ [ - 'id' => 42, + 'id' => '42', 'share_type' => IShare::TYPE_ROOM, 'uid_owner' => 'initiator', 'displayname_owner' => 'initiator', @@ -4759,6 +4813,8 @@ class ShareAPIControllerTest extends TestCase { 'label' => '', 'can_edit' => false, 'can_delete' => false, + 'item_size' => 123456, + 'item_mtime' => 1234567890, 'attributes' => null, ], $share, true, [ 'share_with_displayname' => 'recipientRoomName' diff --git a/apps/files_sharing/tests/js/appSpec.js b/apps/files_sharing/tests/js/appSpec.js deleted file mode 100644 index 4d2e5211d7c..00000000000 --- a/apps/files_sharing/tests/js/appSpec.js +++ /dev/null @@ -1,125 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -describe('OCA.Sharing.App tests', function() { - var App = OCA.Sharing.App; - var fileListIn; - var fileListOut; - - beforeEach(function() { - $('#testArea').append( - '<div id="app-navigation">' + - '<ul><li data-id="files"><a>Files</a></li>' + - '<li data-id="sharingin"><a></a></li>' + - '<li data-id="sharingout"><a></a></li>' + - '</ul></div>' + - '<div id="app-content">' + - '<div id="app-content-files" class="hidden">' + - '</div>' + - '<div id="app-content-sharingin" class="hidden">' + - '</div>' + - '<div id="app-content-sharingout" class="hidden">' + - '</div>' + - '</div>' + - '</div>' - ); - fileListIn = App.initSharingIn($('#app-content-sharingin')); - fileListOut = App.initSharingOut($('#app-content-sharingout')); - }); - afterEach(function() { - App.destroy(); - }); - - describe('initialization', function() { - it('inits sharing-in list on show', function() { - expect(fileListIn._sharedWithUser).toEqual(true); - }); - it('inits sharing-out list on show', function() { - expect(fileListOut._sharedWithUser).toBeFalsy(); - }); - }); - describe('file actions', function() { - it('provides default file actions', function() { - _.each([fileListIn, fileListOut], function(fileList) { - var fileActions = fileList.fileActions; - - expect(fileActions.actions.all).toBeDefined(); - expect(fileActions.actions.all.Delete).toBeDefined(); - expect(fileActions.actions.all.Rename).toBeDefined(); - expect(fileActions.actions.all.Download).toBeDefined(); - - expect(fileActions.defaults.dir).toEqual('Open'); - }); - }); - it('provides custom file actions', function() { - var actionStub = sinon.stub(); - // regular file action - OCA.Files.fileActions.register( - 'all', - 'RegularTest', - OC.PERMISSION_READ, - OC.imagePath('core', 'actions/shared'), - actionStub - ); - - App._inFileList = null; - fileListIn = App.initSharingIn($('#app-content-sharingin')); - - expect(fileListIn.fileActions.actions.all.RegularTest).toBeDefined(); - }); - it('redirects to files app when opening a directory', function() { - var oldList = OCA.Files.App.fileList; - // dummy new list to make sure it exists - OCA.Files.App.fileList = new OCA.Files.FileList($('<table><thead></thead><tbody></tbody></table>')); - - var setActiveViewStub = sinon.stub(OCA.Files.App, 'setActiveView'); - // create dummy table so we can click the dom - var $table = '<table><thead></thead><tbody class="files-fileList"></tbody></table>'; - $('#app-content-sharingin').append($table); - - App._inFileList = null; - fileListIn = App.initSharingIn($('#app-content-sharingin')); - - fileListIn.setFiles([{ - name: 'testdir', - type: 'dir', - path: '/somewhere/inside/subdir', - counterParts: ['user2'], - shareOwner: 'user2' - }]); - - fileListIn.findFileEl('testdir').find('td .nametext').click(); - - expect(OCA.Files.App.fileList.getCurrentDirectory()).toEqual('/somewhere/inside/subdir/testdir'); - - expect(setActiveViewStub.calledOnce).toEqual(true); - expect(setActiveViewStub.calledWith('files')).toEqual(true); - - setActiveViewStub.restore(); - - // restore old list - OCA.Files.App.fileList = oldList; - }); - }); -}); diff --git a/build/integration/sharing_features/sharing-v1-part4.feature b/build/integration/sharing_features/sharing-v1-part4.feature new file mode 100644 index 00000000000..ae4e69f2622 --- /dev/null +++ b/build/integration/sharing_features/sharing-v1-part4.feature @@ -0,0 +1,41 @@ +Feature: sharing + Background: + Given using api version "1" + Given using new dav path + +# See sharing-v1-part3.feature + +Scenario: Creating a new share of a file shows size and mtime + Given user "user0" exists + And user "user1" exists + And As an "user0" + And parameter "shareapi_default_permissions" of app "core" is set to "7" + When creating a share with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | item_size | A_NUMBER | + | item_mtime | A_NUMBER | + +Scenario: Creating a new share of a file you own shows the file permissions + Given user "user0" exists + And user "user1" exists + And As an "user0" + And parameter "shareapi_default_permissions" of app "core" is set to "7" + When creating a share with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | item_permissions | 27 | |