aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorF. E Noel Nfebe <fenn25.fn@gmail.com>2025-02-06 13:50:57 +0100
committerGitHub <noreply@github.com>2025-02-06 13:50:57 +0100
commit7af66eaf62010a33c1f860f7400148f553681e2c (patch)
treef5e0e31d471b5f006d3d5294e8c18bc148d22687 /apps
parent9c3ef8eada7085feace2bb8fcdfa9be3288cf805 (diff)
parenta5442526b5c3bc0e33213d306842ab8b6a2a8685 (diff)
downloadnextcloud-server-7af66eaf62010a33c1f860f7400148f553681e2c.tar.gz
nextcloud-server-7af66eaf62010a33c1f860f7400148f553681e2c.zip
Merge pull request #50655 from nextcloud/fix/share-sidebar-bugs
enh: Fix display default expire date, add tests & tiny refactors
Diffstat (limited to 'apps')
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php53
-rw-r--r--apps/files_sharing/src/components/SharingEntryLink.vue17
-rw-r--r--apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue13
-rw-r--r--apps/files_sharing/src/components/SharingInput.vue5
-rw-r--r--apps/files_sharing/src/mixins/SharesMixin.js16
-rw-r--r--apps/files_sharing/src/views/SharingDetailsTab.vue8
6 files changed, 65 insertions, 47 deletions
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 9716e8f2772..f6fc584529b 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -45,6 +45,7 @@ use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\ITagManager;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
@@ -280,7 +281,7 @@ class ShareAPIController extends OCSController {
/** @var array{share_with_displayname: string, share_with_link: string, share_with?: string, token?: string} $roomShare */
$roomShare = $this->getRoomShareHelper()->formatShare($share);
$result = array_merge($result, $roomShare);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
}
} elseif ($share->getShareType() === IShare::TYPE_DECK) {
$result['share_with'] = $share->getSharedWith();
@@ -290,7 +291,7 @@ class ShareAPIController extends OCSController {
/** @var array{share_with: string, share_with_displayname: string, share_with_link: string} $deckShare */
$deckShare = $this->getDeckShareHelper()->formatShare($share);
$result = array_merge($result, $deckShare);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
}
} elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
$result['share_with'] = $share->getSharedWith();
@@ -300,7 +301,7 @@ class ShareAPIController extends OCSController {
/** @var array{share_with: string, share_with_displayname: string, token: string} $scienceMeshShare */
$scienceMeshShare = $this->getSciencemeshShareHelper()->formatShare($share);
$result = array_merge($result, $scienceMeshShare);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
}
}
@@ -470,7 +471,7 @@ class ShareAPIController extends OCSController {
$share = $this->formatShare($share);
if ($include_tags) {
- $share = Helper::populateTags([$share], \OC::$server->getTagManager());
+ $share = Helper::populateTags([$share], \OCP\Server::get(ITagManager::class));
} else {
$share = [$share];
}
@@ -637,7 +638,9 @@ class ShareAPIController extends OCSController {
$share = $this->setShareAttributes($share, $attributes);
}
- // Expire date
+ // Expire date checks
+ // Normally, null means no expiration date but we still set the default for backwards compatibility
+ // If the client sends an empty string, we set noExpirationDate to true
if ($expireDate !== null) {
if ($expireDate !== '') {
try {
@@ -751,7 +754,7 @@ class ShareAPIController extends OCSController {
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
} elseif ($shareType === IShare::TYPE_CIRCLE) {
- if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
+ if (!\OCP\Server::get(IAppManager::class)->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
throw new OCSNotFoundException($this->l->t('You cannot share to a Team if the app is not enabled'));
}
@@ -766,19 +769,19 @@ class ShareAPIController extends OCSController {
} elseif ($shareType === IShare::TYPE_ROOM) {
try {
$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
}
} elseif ($shareType === IShare::TYPE_DECK) {
try {
$this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
}
} elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
try {
$this->getSciencemeshShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support ScienceMesh shares', [$node->getPath()]));
}
} else {
@@ -839,7 +842,7 @@ class ShareAPIController extends OCSController {
}
if ($includeTags) {
- $formatted = Helper::populateTags($formatted, \OC::$server->getTagManager());
+ $formatted = Helper::populateTags($formatted, \OCP\Server::get(ITagManager::class));
}
return $formatted;
@@ -1093,7 +1096,7 @@ class ShareAPIController extends OCSController {
if ($includeTags) {
$formatted =
- Helper::populateTags($formatted, \OC::$server->getTagManager());
+ Helper::populateTags($formatted, \OCP\Server::get(ITagManager::class));
}
return $formatted;
@@ -1522,7 +1525,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_ROOM) {
try {
return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1530,7 +1533,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_DECK) {
try {
return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1538,7 +1541,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
try {
return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1656,7 +1659,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_ROOM) {
try {
return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1664,7 +1667,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_DECK) {
try {
return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1672,7 +1675,7 @@ class ShareAPIController extends OCSController {
if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
try {
return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
@@ -1798,10 +1801,10 @@ class ShareAPIController extends OCSController {
* Returns the helper of ShareAPIController for room shares.
*
* If the Talk application is not enabled or the helper is not available
- * a QueryException is thrown instead.
+ * a ContainerExceptionInterface is thrown instead.
*
* @return \OCA\Talk\Share\Helper\ShareAPIController
- * @throws QueryException
+ * @throws ContainerExceptionInterface
*/
private function getRoomShareHelper() {
if (!$this->appManager->isEnabledForUser('spreed')) {
@@ -1815,10 +1818,10 @@ class ShareAPIController extends OCSController {
* Returns the helper of ShareAPIHelper for deck shares.
*
* If the Deck application is not enabled or the helper is not available
- * a QueryException is thrown instead.
+ * a ContainerExceptionInterface is thrown instead.
*
* @return \OCA\Deck\Sharing\ShareAPIHelper
- * @throws QueryException
+ * @throws ContainerExceptionInterface
*/
private function getDeckShareHelper() {
if (!$this->appManager->isEnabledForUser('deck')) {
@@ -1832,10 +1835,10 @@ class ShareAPIController extends OCSController {
* Returns the helper of ShareAPIHelper for sciencemesh shares.
*
* If the sciencemesh application is not enabled or the helper is not available
- * a QueryException is thrown instead.
+ * a ContainerExceptionInterface is thrown instead.
*
* @return \OCA\Deck\Sharing\ShareAPIHelper
- * @throws QueryException
+ * @throws ContainerExceptionInterface
*/
private function getSciencemeshShareHelper() {
if (!$this->appManager->isEnabledForUser('sciencemesh')) {
@@ -1968,7 +1971,7 @@ class ShareAPIController extends OCSController {
return true;
}
- if ($share->getShareType() === IShare::TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles')
+ if ($share->getShareType() === IShare::TYPE_CIRCLE && \OCP\Server::get(IAppManager::class)->isEnabledForUser('circles')
&& class_exists('\OCA\Circles\Api\v1\Circles')) {
$hasCircleId = (str_ends_with($share->getSharedWith(), ']'));
$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
@@ -1984,7 +1987,7 @@ class ShareAPIController extends OCSController {
return true;
}
return false;
- } catch (QueryException $e) {
+ } catch (ContainerExceptionInterface $e) {
return false;
}
}
diff --git a/apps/files_sharing/src/components/SharingEntryLink.vue b/apps/files_sharing/src/components/SharingEntryLink.vue
index 28c72bfc98a..c52a587b89f 100644
--- a/apps/files_sharing/src/components/SharingEntryLink.vue
+++ b/apps/files_sharing/src/components/SharingEntryLink.vue
@@ -86,12 +86,13 @@
:checked.sync="defaultExpirationDateEnabled"
:disabled="pendingEnforcedExpirationDate || saving"
class="share-link-expiration-date-checkbox"
- @change="onDefaultExpirationDateEnabledChange">
+ @change="onExpirationDateToggleChange">
{{ config.isDefaultExpireDateEnforced ? t('files_sharing', 'Enable link expiration (enforced)') : t('files_sharing', 'Enable link expiration') }}
</NcActionCheckbox>
<!-- expiration date -->
<NcActionInput v-if="(pendingDefaultExpirationDate || pendingEnforcedExpirationDate) && defaultExpirationDateEnabled"
+ data-cy-files-sharing-expiration-date-input
class="share-link-expire-date"
:label="pendingEnforcedExpirationDate ? t('files_sharing', 'Enter expiration date (enforced)') : t('files_sharing', 'Enter expiration date')"
:disabled="saving"
@@ -101,7 +102,7 @@
type="date"
:min="dateTomorrow"
:max="maxExpirationDateEnforced"
- @input="onExpirationChange /* let's not submit when picked, the user might want to still edit or copy the password */">
+ @change="expirationDateChanged($event)">
<template #icon>
<IconCalendarBlank :size="20" />
</template>
@@ -597,6 +598,9 @@ export default {
},
mounted() {
this.defaultExpirationDateEnabled = this.config.defaultExpirationDate instanceof Date
+ if (this.share && this.isNewShare) {
+ this.share.expireDate = this.defaultExpirationDateEnabled ? this.formatDateToString(this.config.defaultExpirationDate) : ''
+ }
},
methods: {
@@ -715,7 +719,7 @@ export default {
path,
shareType: ShareType.Link,
password: share.password,
- expireDate: share.expireDate,
+ expireDate: share.expireDate ?? '',
attributes: JSON.stringify(this.fileInfo.shareAttributes),
// we do not allow setting the publicUpload
// before the share creation.
@@ -871,9 +875,14 @@ export default {
this.onPasswordSubmit()
this.onNoteSubmit()
},
- onDefaultExpirationDateEnabledChange(enabled) {
+ onExpirationDateToggleChange(enabled) {
this.share.expireDate = enabled ? this.formatDateToString(this.config.defaultExpirationDate) : ''
},
+ expirationDateChanged(event) {
+ const date = event.target.value
+ this.onExpirationChange(date)
+ this.defaultExpirationDateEnabled = !!date
+ },
/**
* Cancel the share creation
diff --git a/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue b/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
index 565bee1d821..fde4f0e7091 100644
--- a/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
+++ b/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
@@ -29,6 +29,7 @@
<script>
import { ShareType } from '@nextcloud/sharing'
+import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import DropdownIcon from 'vue-material-design-icons/TriangleSmallDown.vue'
import SharesMixin from '../mixins/SharesMixin.js'
import ShareDetails from '../mixins/ShareDetails.js'
@@ -145,7 +146,17 @@ export default {
created() {
this.selectedOption = this.preSelectedOption
},
-
+ mounted() {
+ subscribe('update:share', (share) => {
+ if (share.id === this.share.id) {
+ this.share.permissions = share.permissions
+ this.selectedOption = this.preSelectedOption
+ }
+ })
+ },
+ unmounted() {
+ unsubscribe('update:share')
+ },
methods: {
selectOption(optionLabel) {
this.selectedOption = optionLabel
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index 67fdceae336..689539f737a 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -149,7 +149,10 @@ export default {
},
mounted() {
- this.getRecommendations()
+ if (!this.isExternal) {
+ // We can only recommend users, groups etc for internal shares
+ this.getRecommendations()
+ }
},
methods: {
diff --git a/apps/files_sharing/src/mixins/SharesMixin.js b/apps/files_sharing/src/mixins/SharesMixin.js
index fdd8bbd72fd..c809b650fdf 100644
--- a/apps/files_sharing/src/mixins/SharesMixin.js
+++ b/apps/files_sharing/src/mixins/SharesMixin.js
@@ -110,6 +110,9 @@ export default {
monthFormat: 'MMM',
}
},
+ isNewShare() {
+ return !this.share.id
+ },
isFolder() {
return this.fileInfo.type === 'dir'
},
@@ -210,17 +213,8 @@ export default {
* @param {Date} date
*/
onExpirationChange(date) {
- this.share.expireDate = this.formatDateToString(new Date(date))
- },
-
- /**
- * Uncheck expire date
- * We need this method because @update:checked
- * is ran simultaneously as @uncheck, so
- * so we cannot ensure data is up-to-date
- */
- onExpirationDisable() {
- this.share.expireDate = ''
+ const formattedDate = date ? this.formatDateToString(new Date(date)) : ''
+ this.share.expireDate = formattedDate
},
/**
diff --git a/apps/files_sharing/src/views/SharingDetailsTab.vue b/apps/files_sharing/src/views/SharingDetailsTab.vue
index f50a533eeeb..df420cf7af2 100644
--- a/apps/files_sharing/src/views/SharingDetailsTab.vue
+++ b/apps/files_sharing/src/views/SharingDetailsTab.vue
@@ -115,8 +115,8 @@
:helper-text="t('files_sharing', 'Set the public share link token to something easy to remember or generate a new token. It is not recommended to use a guessable token for shares which contain sensitive information.')"
show-trailing-button
:trailing-button-label="loadingToken ? t('files_sharing', 'Generating…') : t('files_sharing', 'Generate new token')"
- @trailing-button-click="generateNewToken"
- :value.sync="share.token">
+ :value.sync="share.token"
+ @trailing-button-click="generateNewToken">
<template #trailing-button-icon>
<NcLoadingIcon v-if="loadingToken" />
<Refresh v-else :size="20" />
@@ -556,9 +556,6 @@ export default {
isGroupShare() {
return this.share.type === ShareType.Group
},
- isNewShare() {
- return !this.share.id
- },
allowsFileDrop() {
if (this.isFolder && this.config.isPublicUploadEnabled) {
if (this.share.type === ShareType.Link || this.share.type === ShareType.Email) {
@@ -972,6 +969,7 @@ export default {
this.$emit('add:share', this.share)
} else {
this.$emit('update:share', this.share)
+ emit('update:share', this.share)
this.queueUpdate(...permissionsAndAttributes)
}