Skip to content

Commit 02679ae

Browse files
susnuxbackportbot[bot]
authored andcommitted
fix(files_versions): correctly show version author also for shared files
The users endpoint is not available for other users if the current user has no admin privileges, so instead use the displaynames endpoint. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent ec4187c commit 02679ae

File tree

4 files changed

+101
-34
lines changed

4 files changed

+101
-34
lines changed

apps/files_versions/src/components/Version.vue

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,19 @@
4343
<div class="version__info">
4444
<div v-if="versionLabel"
4545
class="version__info__label"
46+
data-cy-files-version-label
4647
:title="versionLabel">
4748
{{ versionLabel }}
4849
</div>
49-
<div v-if="versionAuthor" class="version__info">
50+
<div v-if="versionAuthor"
51+
class="version__info"
52+
data-cy-files-version-author-name>
5053
<span v-if="versionLabel">•</span>
5154
<NcAvatar class="avatar"
5255
:user="version.author"
53-
:size="16"
54-
:disable-menu="true"
55-
:disable-tooltip="true"
56+
:size="20"
57+
disable-menu
58+
disable-tooltip
5659
:show-user-status="false" />
5760
<div>{{ versionAuthor }}</div>
5861
</div>
@@ -65,7 +68,7 @@
6568
<NcDateTime class="version__info__date"
6669
relative-time="short"
6770
:timestamp="version.mtime" />
68-
<!-- Separate dot to improve alignement -->
71+
<!-- Separate dot to improve alignment -->
6972
<span>•</span>
7073
<span>{{ humanReadableSize }}</span>
7174
</div>
@@ -303,21 +306,26 @@ export default defineComponent({
303306
},
304307
305308
async fetchDisplayName() {
306-
// check to make sure that we have a valid author - in case database did not migrate, null author, etc.
307-
if (this.version.author) {
309+
this.versionAuthor = null
310+
if (!this.version.author) {
311+
return
312+
}
313+
314+
if (this.version.author === getCurrentUser()?.uid) {
315+
this.versionAuthor = t('files_versions', 'You')
316+
} else {
308317
try {
309-
const { data } = await axios.get(generateOcsUrl(`/cloud/users/${this.version.author}`))
310-
this.versionAuthor = data.ocs.data.displayname
311-
} catch (e) {
312-
// Promise got rejected - default to null author to not try to load author profile
313-
this.versionAuthor = null
318+
const { data } = await axios.post(generateUrl('/displaynames'), { users: [this.version.author] })
319+
this.versionAuthor = data.users[this.version.author]
320+
} catch (error) {
321+
logger.warn('Could not load user display name', { error })
314322
}
315323
}
316324
},
317325
318326
click() {
319327
if (!this.canView) {
320-
window.location = this.downloadURL
328+
window.location.href = this.downloadURL
321329
return
322330
}
323331
this.$emit('click', { version: this.version })

apps/files_versions/src/views/VersionTab.vue

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,27 @@
1717
-->
1818
<template>
1919
<div class="versions-tab__container">
20-
<VirtualScrolling :sections="sections"
20+
<VirtualScrolling v-slot="{ visibleSections }"
21+
:sections="sections"
2122
:header-height="0">
22-
<template slot-scope="{visibleSections}">
23-
<ul data-files-versions-versions-list>
24-
<template v-if="visibleSections.length === 1">
25-
<Version v-for="(row) of visibleSections[0].rows"
26-
:key="row.items[0].mtime"
27-
:can-view="canView"
28-
:can-compare="canCompare"
29-
:load-preview="isActive"
30-
:version="row.items[0]"
31-
:file-info="fileInfo"
32-
:is-current="row.items[0].mtime === fileInfo.mtime"
33-
:is-first-version="row.items[0].mtime === initialVersionMtime"
34-
@click="openVersion"
35-
@compare="compareVersion"
36-
@restore="handleRestore"
37-
@label-update-request="handleLabelUpdateRequest(row.items[0])"
38-
@delete="handleDelete" />
39-
</template>
40-
</ul>
41-
</template>
23+
<ul :aria-label="t('files_versions', 'File versions')" data-files-versions-versions-list>
24+
<template v-if="visibleSections.length === 1">
25+
<Version v-for="(row) of visibleSections[0].rows"
26+
:key="row.items[0].mtime"
27+
:can-view="canView"
28+
:can-compare="canCompare"
29+
:load-preview="isActive"
30+
:version="row.items[0]"
31+
:file-info="fileInfo"
32+
:is-current="row.items[0].mtime === fileInfo.mtime"
33+
:is-first-version="row.items[0].mtime === initialVersionMtime"
34+
@click="openVersion"
35+
@compare="compareVersion"
36+
@restore="handleRestore"
37+
@label-update-request="handleLabelUpdateRequest(row.items[0])"
38+
@delete="handleDelete" />
39+
</template>
40+
</ul>
4241
<NcLoadingIcon v-if="loading" slot="loader" class="files-list-viewer__loader" />
4342
</VirtualScrolling>
4443
<NcModal v-if="showVersionLabelForm"

cypress/e2e/files_versions/version_creation.cy.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,18 @@ describe('Versions creation', () => {
4747
cy.get('[data-files-versions-version]').eq(2).contains('Initial version')
4848
})
4949
})
50+
51+
it('See yourself as version author', () => {
52+
cy.visit('/apps/files')
53+
openVersionsPanel(randomFileName)
54+
55+
cy.findByRole('tabpanel', { name: 'Versions' })
56+
.findByRole('list', { name: 'File versions' })
57+
.findAllByRole('listitem')
58+
.should('have.length', 3)
59+
.first()
60+
.find('[data-cy-files-version-author-name]')
61+
.should('exist')
62+
.and('contain.text', 'You')
63+
})
5064
})
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
import type { User } from '@nextcloud/cypress'
6+
import { openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
7+
import { navigateToFolder, triggerActionForFile } from '../files/FilesUtils.ts'
8+
9+
describe('Versions on shares', () => {
10+
const randomSharedFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
11+
const randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
12+
const randomFilePath = `${randomSharedFolderName}/${randomFileName}`
13+
let alice: User
14+
let bob: User
15+
16+
before(() => {
17+
cy.createRandomUser()
18+
.then((user) => {
19+
alice = user
20+
})
21+
.then(() => {
22+
cy.mkdir(alice, `/${randomSharedFolderName}`)
23+
return setupTestSharedFileFromUser(alice, randomSharedFolderName, {})
24+
})
25+
.then((user) => { bob = user })
26+
.then(() => uploadThreeVersions(alice, randomFilePath))
27+
})
28+
29+
it('See sharees display name as author', () => {
30+
cy.login(bob)
31+
cy.visit('/apps/files')
32+
33+
navigateToFolder(randomSharedFolderName)
34+
35+
triggerActionForFile(randomFileName, 'details')
36+
cy.findByRole('tab', { name: 'Versions' }).click()
37+
38+
cy.findByRole('tabpanel', { name: 'Versions' })
39+
.findByRole('list', { name: 'File versions' })
40+
.findAllByRole('listitem')
41+
.first()
42+
.find('[data-cy-files-version-author-name]')
43+
.should('be.visible')
44+
.and('contain.text', alice.userId)
45+
})
46+
})

0 commit comments

Comments
 (0)