Skip to content

Commit

Permalink
Merge pull request #50192 from nextcloud/fix/files_sharing/sharing-en…
Browse files Browse the repository at this point in the history
…try-link-override-expiration-date

fix(files_sharing): Stop overwriting the share expiration date with the default expiration date
  • Loading branch information
susnux authored Jan 15, 2025
2 parents 0cad072 + ddd70c9 commit 6da5897
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 18 deletions.
5 changes: 1 addition & 4 deletions apps/files_sharing/src/components/SharingEntryLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -590,10 +590,7 @@ export default {
},
},
mounted() {
if (this.share) {
this.defaultExpirationDateEnabled = this.config.defaultExpirationDate instanceof Date
this.share.expireDate = this.defaultExpirationDateEnabled ? this.formatDateToString(this.config.defaultExpirationDate) : ''
}
this.defaultExpirationDateEnabled = this.config.defaultExpirationDate instanceof Date
},

methods: {
Expand Down
7 changes: 4 additions & 3 deletions apps/files_sharing/src/mixins/SharesMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export default {
return this.config.isDefaultExpireDateEnforced
}
if (this.isRemoteShare) {
return this.config.isDefaultRemoteExpireDateEnforced
return this.config.isDefaultRemoteExpireDateEnforced
}
return this.config.isDefaultInternalExpireDateEnforced
},
Expand Down Expand Up @@ -209,9 +209,10 @@ export default {
*
* @param {Date} date
*/
onExpirationChange: debounce(function(date) {
onExpirationChange(date) {
this.share.expireDate = this.formatDateToString(new Date(date))
}, 500),
},

/**
* Uncheck expire date
* We need this method because @update:checked
Expand Down
3 changes: 2 additions & 1 deletion apps/files_sharing/src/views/SharingDetailsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@
:value="new Date(share.expireDate ?? dateTomorrow)"
:min="dateTomorrow"
:max="maxExpirationDateEnforced"
:hide-label="true"
hide-label
:label="t('files_sharing', 'Expiration date')"
:placeholder="t('files_sharing', 'Expiration date')"
type="date"
@input="onExpirationChange" />
Expand Down
21 changes: 18 additions & 3 deletions cypress/e2e/files_sharing/FilesSharingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface ShareSetting {
share: boolean
download: boolean
note: string
expiryDate: Date
}

export function createShare(fileName: string, username: string, shareSettings: Partial<ShareSetting> = {}) {
Expand All @@ -31,15 +32,20 @@ export function createShare(fileName: string, username: string, shareSettings: P
updateShare(fileName, 0, shareSettings)
}

export function openSharingDetails(index: number) {
cy.get('#app-sidebar-vue').within(() => {
cy.get('[data-cy-files-sharing-share-actions]').eq(index).click()
cy.get('[data-cy-files-sharing-share-permissions-bundle="custom"]').click()
})
}

export function updateShare(fileName: string, index: number, shareSettings: Partial<ShareSetting> = {}) {
openSharingPanel(fileName)
openSharingDetails(index)

cy.intercept({ times: 1, method: 'PUT', url: '**/apps/files_sharing/api/v1/shares/*' }).as('updateShare')

cy.get('#app-sidebar-vue').within(() => {
cy.get('[data-cy-files-sharing-share-actions]').eq(index).click()
cy.get('[data-cy-files-sharing-share-permissions-bundle="custom"]').click()

if (shareSettings.download !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="download"]').find('input').as('downloadCheckbox')
if (shareSettings.download) {
Expand Down Expand Up @@ -89,10 +95,19 @@ export function updateShare(fileName: string, index: number, shareSettings: Part
cy.findByRole('textbox', { name: /note to recipient/i }).type(shareSettings.note)
}

if (shareSettings.expiryDate !== undefined) {
cy.findByRole('checkbox', { name: /expiration date/i })
.check({ force: true, scrollBehavior: 'nearest' })
cy.get('#share-date-picker')
.type(`${shareSettings.expiryDate.getFullYear()}-${String(shareSettings.expiryDate.getMonth() + 1).padStart(2, '0')}-${String(shareSettings.expiryDate.getDate()).padStart(2, '0')}`)
}

cy.get('[data-cy-files-sharing-share-editor-action="save"]').click({ scrollBehavior: 'nearest' })

cy.wait('@updateShare')
})
// close all toasts
cy.get('.toast-success').findAllByRole('button').click({ force: true, multiple: true })
}

export function openSharingPanel(fileName: string) {
Expand Down
128 changes: 128 additions & 0 deletions cypress/e2e/files_sharing/expiry-date.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*!
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { User } from '@nextcloud/cypress'
import { closeSidebar } from '../files/FilesUtils.ts'
import { createShare, openSharingDetails, openSharingPanel, updateShare } from './FilesSharingUtils.ts'

describe('files_sharing: Expiry date', () => {
const expectedDefaultDate = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000)
const expectedDefaultDateString = `${expectedDefaultDate.getFullYear()}-${String(expectedDefaultDate.getMonth() + 1).padStart(2, '0')}-${String(expectedDefaultDate.getDate()).padStart(2, '0')}`
const fortnight = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000)
const fortnightString = `${fortnight.getFullYear()}-${String(fortnight.getMonth() + 1).padStart(2, '0')}-${String(fortnight.getDate()).padStart(2, '0')}`

let alice: User
let bob: User

before(() => {
// Ensure we have the admin setting setup for default dates with 2 days in the future
cy.runOccCommand('config:app:set --value yes core shareapi_default_internal_expire_date')
cy.runOccCommand('config:app:set --value 2 core shareapi_internal_expire_after_n_days')

cy.createRandomUser().then((user) => {
alice = user
cy.login(alice)
})
cy.createRandomUser().then((user) => {
bob = user
})
})

after(() => {
cy.runOccCommand('config:app:delete core shareapi_default_internal_expire_date')
cy.runOccCommand('config:app:delete core shareapi_enforce_internal_expire_date')
cy.runOccCommand('config:app:delete core shareapi_internal_expire_after_n_days')
})

beforeEach(() => {
cy.runOccCommand('config:app:delete core shareapi_enforce_internal_expire_date')
})

it('See default expiry date is set and enforced', () => {
// Enforce the date
cy.runOccCommand('config:app:set --value yes core shareapi_enforce_internal_expire_date')
const dir = 'defaultExpiryDateEnforced'
prepareDirectory(dir)

validateExpiryDate(dir, expectedDefaultDateString)
cy.findByRole('checkbox', { name: /expiration date/i })
.should('be.checked')
.and('be.disabled')
})

it('See default expiry date is set also if not enforced', () => {
const dir = 'defaultExpiryDate'
prepareDirectory(dir)

validateExpiryDate(dir, expectedDefaultDateString)
cy.findByRole('checkbox', { name: /expiration date/i })
.should('be.checked')
.and('not.be.disabled')
.check({ force: true, scrollBehavior: 'nearest' })
})

it('Can set custom expiry date', () => {
const dir = 'customExpiryDate'
prepareDirectory(dir)
updateShare(dir, 0, { expiryDate: fortnight })
validateExpiryDate(dir, fortnightString)
})

it('Custom expiry date survives reload', () => {
const dir = 'customExpiryDateReload'
prepareDirectory(dir)
updateShare(dir, 0, { expiryDate: fortnight })
validateExpiryDate(dir, fortnightString)

cy.visit('/apps/files')
validateExpiryDate(dir, fortnightString)
})

/**
* Regression test for https://github.com/nextcloud/server/pull/50192
* Ensure that admin default settings do not always override the user set value.
*/
it('Custom expiry date survives unrelated update', () => {
const dir = 'customExpiryUnrelatedChanges'
prepareDirectory(dir)
updateShare(dir, 0, { expiryDate: fortnight })
validateExpiryDate(dir, fortnightString)

closeSidebar()
updateShare(dir, 0, { note: 'Only note changed' })
validateExpiryDate(dir, fortnightString)

cy.visit('/apps/files')
validateExpiryDate(dir, fortnightString)
})

/**
* Prepare directory, login and share to bob
*
* @param name The directory name
*/
function prepareDirectory(name: string) {
cy.mkdir(alice, `/${name}`)
cy.login(alice)
cy.visit('/apps/files')
createShare(name, bob.userId)
}

/**
* Validate expiry date on a share
*
* @param filename The filename to validate
* @param expectedDate The expected date in YYYY-MM-dd
*/
function validateExpiryDate(filename: string, expectedDate: string) {
openSharingPanel(filename)
openSharingDetails(0)

cy.get('#share-date-picker')
.should('exist')
.and('have.value', expectedDate)
}

})
2 changes: 2 additions & 0 deletions dist/467-467.js

Large diffs are not rendered by default.

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

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/467-467.js.map.license
2 changes: 0 additions & 2 deletions dist/9701-9701.js

This file was deleted.

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

This file was deleted.

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

This file was deleted.

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.

0 comments on commit 6da5897

Please sign in to comment.