Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions apps/files_sharing/src/components/SharingEntryLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,14 @@
</template>

<script>
import { showError, showSuccess } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
import { t } from '@nextcloud/l10n'
import moment from '@nextcloud/moment'
import { generateUrl, getBaseUrl } from '@nextcloud/router'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { ShareType } from '@nextcloud/sharing'
import VueQrcode from '@chenfengyuan/vue-qrcode'
import moment from '@nextcloud/moment'

import VueQrcode from '@chenfengyuan/vue-qrcode'
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
import NcActionCheckbox from '@nextcloud/vue/components/NcActionCheckbox'
import NcActionInput from '@nextcloud/vue/components/NcActionInput'
Expand Down Expand Up @@ -258,7 +259,7 @@ import GeneratePassword from '../utils/GeneratePassword.ts'
import Share from '../models/Share.ts'
import SharesMixin from '../mixins/SharesMixin.js'
import ShareDetails from '../mixins/ShareDetails.js'
import { getLoggerBuilder } from '@nextcloud/logger'
import logger from '../services/logger.ts'

export default {
name: 'SharingEntryLink',
Expand Down Expand Up @@ -313,10 +314,6 @@ export default {

ExternalLegacyLinkActions: OCA.Sharing.ExternalLinkActions.state,
ExternalShareActions: OCA.Sharing.ExternalShareActions.state,
logger: getLoggerBuilder()
.setApp('files_sharing')
.detectUser()
.build(),

// tracks whether modal should be opened or not
showQRCode: false,
Expand All @@ -330,33 +327,35 @@ export default {
* @return {string}
*/
title() {
const l10nOptions = { escape: false /* no escape as this string is already escaped by Vue */ }

// if we have a valid existing share (not pending)
if (this.share && this.share.id) {
if (!this.isShareOwner && this.share.ownerDisplayName) {
if (this.isEmailShareType) {
return t('files_sharing', '{shareWith} by {initiator}', {
shareWith: this.share.shareWith,
initiator: this.share.ownerDisplayName,
})
}, l10nOptions)
}
return t('files_sharing', 'Shared via link by {initiator}', {
initiator: this.share.ownerDisplayName,
})
}, l10nOptions)
}
if (this.share.label && this.share.label.trim() !== '') {
if (this.isEmailShareType) {
if (this.isFileRequest) {
return t('files_sharing', 'File request ({label})', {
label: this.share.label.trim(),
})
}, l10nOptions)
}
return t('files_sharing', 'Mail share ({label})', {
label: this.share.label.trim(),
})
}, l10nOptions)
}
return t('files_sharing', 'Share link ({label})', {
label: this.share.label.trim(),
})
}, l10nOptions)
}
if (this.isEmailShareType) {
if (!this.share.shareWith || this.share.shareWith.trim() === '') {
Expand Down Expand Up @@ -391,6 +390,7 @@ export default {
}
return null
},

passwordExpirationTime() {
if (this.share.passwordExpirationTime === null) {
return null
Expand Down Expand Up @@ -613,7 +613,7 @@ export default {
* @param {boolean} shareReviewComplete if the share was reviewed
*/
async onNewLinkShare(shareReviewComplete = false) {
this.logger.debug('onNewLinkShare called (with this.share)', this.share)
logger.debug('onNewLinkShare called (with this.share)', this.share)
// do not run again if already loading
if (this.loading) {
return
Expand All @@ -628,15 +628,15 @@ export default {
shareDefaults.expiration = this.formatDateToString(this.config.defaultExpirationDate)
}

this.logger.debug('Missing required properties?', this.enforcedPropertiesMissing)
logger.debug('Missing required properties?', this.enforcedPropertiesMissing)
// Do not push yet if we need a password or an expiration date: show pending menu
// A share would require a review for example is default expiration date is set but not enforced, this allows
// the user to review the share and remove the expiration date if they don't want it
if ((this.sharePolicyHasEnforcedProperties && this.enforcedPropertiesMissing) || this.shareRequiresReview(shareReviewComplete === true)) {
this.pending = true
this.shareCreationComplete = false

this.logger.info('Share policy requires a review or has mandated properties (password, expirationDate)...')
logger.info('Share policy requires a review or has mandated properties (password, expirationDate)...')

// ELSE, show the pending popovermenu
// if password default or enforced, pre-fill with random one
Expand Down Expand Up @@ -664,13 +664,13 @@ export default {
// if the share is valid, create it on the server
if (this.checkShare(this.share)) {
try {
this.logger.info('Sending existing share to server', this.share)
logger.info('Sending existing share to server', this.share)
await this.pushNewLinkShare(this.share, true)
this.shareCreationComplete = true
this.logger.info('Share created on server', this.share)
logger.info('Share created on server', this.share)
} catch (e) {
this.pending = false
this.logger.error('Error creating share', e)
logger.error('Error creating share', e)
return false
}
return true
Expand Down
45 changes: 45 additions & 0 deletions cypress/e2e/files_sharing/public-share/sidebar-tab.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*!
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { User } from "@nextcloud/cypress"
import { createShare } from "./FilesSharingUtils"
import { createLinkShare, openLinkShareDetails } from "./PublicShareUtils"

describe('files_sharing: sidebar tab', () => {
let alice: User

beforeEach(() => {
cy.createRandomUser()
.then((user) => {
alice = user
cy.mkdir(user, '/test')
cy.login(user)
cy.visit('/apps/files')
})
})

/**
* Regression tests of https://github.com/nextcloud/server/issues/53566
* Where the ' char was shown as &#39;
*/
it('correctly lists shares by label with special characters', () => {
createLinkShare({ user: alice }, 'test')
openLinkShareDetails(0)
cy.findByRole('textbox', { name: /share label/i })
.should('be.visible')
.type('Alice\' share')

cy.intercept('PUT', '**/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('PUT')
cy.findByRole('button', { name: /update share/i }).click()
cy.wait('@PUT')

// see the label is shown correctly
cy.findByRole('list', { name: /link shares/i })
.findAllByRole('listitem')
.should('have.length', 1)
.first()
.should('contain.text', 'Share link (Alice\' share)')
})
})
2 changes: 0 additions & 2 deletions dist/7701-7701.js

This file was deleted.

1 change: 0 additions & 1 deletion dist/7701-7701.js.map

This file was deleted.

1 change: 0 additions & 1 deletion dist/7701-7701.js.map.license

This file was deleted.

2 changes: 2 additions & 0 deletions dist/8708-8708.js

Large diffs are not rendered by default.

File renamed without changes.
1 change: 1 addition & 0 deletions dist/8708-8708.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/8708-8708.js.map.license
4 changes: 2 additions & 2 deletions dist/files_sharing-files_sharing_tab.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/files_sharing-files_sharing_tab.js.map

Large diffs are not rendered by default.

Loading