Skip to content

Commit aeb6317

Browse files
committed
fix: Access node owner by top level owner property
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent c8e09d1 commit aeb6317

6 files changed

Lines changed: 115 additions & 13 deletions

File tree

apps/files/src/components/FileEntry/FileEntryActions.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
:close-after-click="!isMenu(action.id)"
3636
:data-cy-files-list-row-action="action.id"
3737
:is-menu="isMenu(action.id)"
38+
:aria-label="action.title?.([source], currentView)"
3839
:title="action.title?.([source], currentView)"
3940
@click="onActionClick(action)">
4041
<template #icon>

apps/files/src/newMenu/newFolder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const entry = {
5959
source,
6060
id: fileid,
6161
mtime: new Date(),
62-
owner: getCurrentUser()?.uid || null,
62+
owner: context.owner,
6363
permissions: Permission.ALL,
6464
root: context?.root || '/files/' + getCurrentUser()?.uid,
6565
// Include mount-type from parent folder as this is inherited

apps/files_sharing/src/actions/sharingStatusAction.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ export const action = new FileAction({
2626
displayName(nodes: Node[]) {
2727
const node = nodes[0]
2828
const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[]
29-
const ownerId = node?.attributes?.['owner-id']
3029

3130
if (shareTypes.length > 0
32-
|| (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
31+
|| (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
3332
return t('files_sharing', 'Shared')
3433
}
3534

@@ -38,15 +37,14 @@ export const action = new FileAction({
3837

3938
title(nodes: Node[]) {
4039
const node = nodes[0]
41-
const ownerId = node?.attributes?.['owner-id']
4240
const ownerDisplayName = node?.attributes?.['owner-display-name']
4341

4442
// Mixed share types
4543
if (Array.isArray(node.attributes?.['share-types']) && node.attributes?.['share-types'].length > 1) {
4644
return t('files_sharing', 'Shared multiple times with different people')
4745
}
4846

49-
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
47+
if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
5048
return t('files_sharing', 'Shared by {ownerDisplayName}', { ownerDisplayName })
5149
}
5250

@@ -69,7 +67,7 @@ export const action = new FileAction({
6967
}
7068

7169
// Group shares
72-
if (shareTypes.includes(ShareType.Grup)
70+
if (shareTypes.includes(ShareType.Group)
7371
|| shareTypes.includes(ShareType.RemoteGroup)) {
7472
return AccountGroupSvg
7573
}
@@ -79,9 +77,8 @@ export const action = new FileAction({
7977
return CircleSvg
8078
}
8179

82-
const ownerId = node?.attributes?.['owner-id']
83-
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
84-
return generateAvatarSvg(ownerId, isExternal(node))
80+
if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
81+
return generateAvatarSvg(node.owner, isExternal(node))
8582
}
8683

8784
return AccountPlusSvg
@@ -93,7 +90,6 @@ export const action = new FileAction({
9390
}
9491

9592
const node = nodes[0]
96-
const ownerId = node?.attributes?.['owner-id']
9793
const shareTypes = node.attributes?.['share-types']
9894
const isMixed = Array.isArray(shareTypes) && shareTypes.length > 0
9995

@@ -104,7 +100,7 @@ export const action = new FileAction({
104100
}
105101

106102
// If the node is shared by someone else
107-
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
103+
if (node.owner !== getCurrentUser()?.uid || isExternal(node)) {
108104
return true
109105
}
110106

apps/files_sharing/src/components/FileListFilterAccount.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ async function updateAvailableAccounts(path: string = '/') {
118118
const { contents } = await currentView.value.getContents(path)
119119
const available = new Map<string, IUserSelectData>()
120120
for (const node of contents) {
121-
const owner = node.owner ?? node.attributes['owner-id']
121+
const owner = node.owner
122122
if (owner && !available.has(owner)) {
123123
available.set(owner, {
124124
id: owner,

apps/files_sharing/src/views/FilesHeaderNoteToRecipient.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'
2929
const folder = ref<Folder>()
3030
const note = computed<string>(() => folder.value?.attributes.note ?? '')
3131
const user = computed(() => {
32-
const id = folder.value?.attributes?.['owner-id']
32+
const id = folder.value?.owner
3333
const displayName = folder.value?.attributes?.['owner-display-name']
3434
if (id !== getCurrentUser()?.uid) {
3535
return {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*!
2+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
import type { User } from '@nextcloud/cypress'
6+
import { createShare } from './FilesSharingUtils.ts'
7+
import { closeSidebar, getRowForFile } from '../files/FilesUtils.ts'
8+
9+
describe('files_sharing: Files inline status action', { testIsolation: true }, () => {
10+
/**
11+
* Regression test of https://github.com/nextcloud/server/issues/45723
12+
*/
13+
it('No "shared" tag when user ID is purely numerical', () => {
14+
const user = {
15+
language: 'en',
16+
password: 'test1234',
17+
userId: String(Math.floor(Math.random() * 1000)),
18+
} as User
19+
cy.createUser(user)
20+
cy.mkdir(user, '/folder')
21+
cy.login(user)
22+
23+
cy.visit('/apps/files')
24+
25+
getRowForFile('folder')
26+
.should('be.visible')
27+
.find('[data-cy-files-list-row-actions]')
28+
.findByRole('button', { name: 'Shared' })
29+
.should('not.exist')
30+
})
31+
32+
describe('', () => {
33+
let user: User
34+
let sharee: User
35+
36+
beforeEach(() => {
37+
cy.createRandomUser().then(($user) => {
38+
user = $user
39+
})
40+
cy.createRandomUser().then(($user) => {
41+
sharee = $user
42+
})
43+
})
44+
45+
it('Render quick option for sharing', () => {
46+
cy.mkdir(user, '/folder')
47+
cy.login(user)
48+
49+
cy.visit('/apps/files')
50+
getRowForFile('folder')
51+
.should('be.visible')
52+
53+
getRowForFile('folder')
54+
.should('be.visible')
55+
.find('[data-cy-files-list-row-actions]')
56+
.findByRole('button', { name: /Show sharing options/ })
57+
.should('be.visible')
58+
.click()
59+
60+
// check the click opened the sidebar
61+
cy.get('[data-cy-sidebar]')
62+
.should('be.visible')
63+
// and ensure the sharing tab is selected
64+
.findByRole('tab', { name: 'Sharing', selected: true })
65+
.should('exist')
66+
})
67+
68+
it('Render inline status action for sharer', () => {
69+
cy.mkdir(user, '/folder')
70+
cy.login(user)
71+
72+
cy.visit('/apps/files')
73+
getRowForFile('folder')
74+
.should('be.visible')
75+
createShare('folder', sharee.userId)
76+
closeSidebar()
77+
78+
getRowForFile('folder')
79+
.should('be.visible')
80+
.find('[data-cy-files-list-row-actions]')
81+
.findByRole('button', { name: 'Shared' })
82+
.should('be.visible')
83+
})
84+
85+
it('Render inline status action for sharee', () => {
86+
cy.mkdir(user, '/folder')
87+
cy.login(user)
88+
89+
cy.visit('/apps/files')
90+
getRowForFile('folder')
91+
.should('be.visible')
92+
createShare('folder', sharee.userId)
93+
closeSidebar()
94+
95+
cy.login(sharee)
96+
cy.visit('/apps/files')
97+
98+
getRowForFile('folder')
99+
.should('be.visible')
100+
.find('[data-cy-files-list-row-actions]')
101+
.findByRole('button', { name: `Shared by ${user.userId}` })
102+
.should('be.visible')
103+
})
104+
})
105+
})

0 commit comments

Comments
 (0)