From f1ff7d7142d34c924c67119c25821a960be871b5 Mon Sep 17 00:00:00 2001 From: nfebe Date: Tue, 24 Feb 2026 16:44:00 +0100 Subject: [PATCH] fix(sharing): Separate max and default expiration dates in link share UI The maxExpirationDateEnforced was using defaultExpirationDate which now returns the default date (linkDefaultExpDays) instead of the maximum (shareapi_expire_after_n_days), preventing users from picking dates between the default and maximum. Signed-off-by: nfebe --- apps/files_sharing/lib/Capabilities.php | 1 + apps/files_sharing/openapi.json | 4 ++++ apps/files_sharing/src/mixins/SharesMixin.js | 2 +- .../src/services/ConfigService.ts | 11 +++++++++ apps/files_sharing/tests/CapabilitiesTest.php | 24 ++++++++++++++++++- build/psalm-baseline.xml | 1 + openapi.json | 4 ++++ 7 files changed, 45 insertions(+), 2 deletions(-) diff --git a/apps/files_sharing/lib/Capabilities.php b/apps/files_sharing/lib/Capabilities.php index 5fed5778b90..41c273d28b1 100644 --- a/apps/files_sharing/lib/Capabilities.php +++ b/apps/files_sharing/lib/Capabilities.php @@ -46,6 +46,7 @@ class Capabilities implements ICapability { * expire_date?: array{ * enabled: bool, * days?: int, + * default_days?: int, * enforced?: bool, * }, * expire_date_internal?: array{ diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json index 8a9a919f676..8332a2cf474 100644 --- a/apps/files_sharing/openapi.json +++ b/apps/files_sharing/openapi.json @@ -80,6 +80,10 @@ "type": "integer", "format": "int64" }, + "default_days": { + "type": "integer", + "format": "int64" + }, "enforced": { "type": "boolean" } diff --git a/apps/files_sharing/src/mixins/SharesMixin.js b/apps/files_sharing/src/mixins/SharesMixin.js index f5e3902814f..928b11873a8 100644 --- a/apps/files_sharing/src/mixins/SharesMixin.js +++ b/apps/files_sharing/src/mixins/SharesMixin.js @@ -151,7 +151,7 @@ export default { maxExpirationDateEnforced() { if (this.isExpiryDateEnforced) { if (this.isPublicShare) { - return this.config.defaultExpirationDate + return this.config.maxExpirationDate } if (this.isRemoteShare) { return this.config.defaultRemoteExpirationDateString diff --git a/apps/files_sharing/src/services/ConfigService.ts b/apps/files_sharing/src/services/ConfigService.ts index 6ccc9e595c6..39c12970723 100644 --- a/apps/files_sharing/src/services/ConfigService.ts +++ b/apps/files_sharing/src/services/ConfigService.ts @@ -24,6 +24,7 @@ type FileSharingCapabilities = { expire_date: { enabled: boolean days: number + default_days: number enforced: boolean } multiple_links: boolean @@ -139,6 +140,16 @@ export default class Config { return null } + /** + * Get the maximum link share expiration date + */ + get maxExpirationDate(): Date | null { + if (this.isDefaultExpireDateEnabled && this.defaultExpireDate !== null) { + return new Date(new Date().setDate(new Date().getDate() + this.defaultExpireDate)) + } + return null + } + /** * Get the default internal expiration date */ diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php index 252459eaaae..6746755c4f4 100644 --- a/apps/files_sharing/tests/CapabilitiesTest.php +++ b/apps/files_sharing/tests/CapabilitiesTest.php @@ -188,6 +188,7 @@ class CapabilitiesTest extends \Test\TestCase { ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '7'], ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], + ['core', 'link_defaultExpDays', '7', '7'], ]; $typedMap = [ @@ -199,7 +200,28 @@ class CapabilitiesTest extends \Test\TestCase { $this->assertArrayHasKey('expire_date', $result['public']); $this->assertIsArray($result['public']['expire_date']); $this->assertTrue($result['public']['expire_date']['enabled']); - $this->assertArrayHasKey('days', $result['public']['expire_date']); + $this->assertSame(7, $result['public']['expire_date']['days']); + $this->assertSame(7, $result['public']['expire_date']['default_days']); + $this->assertFalse($result['public']['expire_date']['enforced']); + } + + public function testLinkExpireDateWithDefaultDays(): void { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_expire_after_n_days', '7', '7'], + ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], + ['core', 'link_defaultExpDays', '7', '3'], + ]; + + $typedMap = [ + ['core', 'shareapi_default_expire_date', true], + ['core', 'shareapi_enforce_expire_date', false], + ]; + + $result = $this->getResults($map, $typedMap); + $this->assertSame(7, $result['public']['expire_date']['days']); + $this->assertSame(3, $result['public']['expire_date']['default_days']); $this->assertFalse($result['public']['expire_date']['enforced']); } diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 9936d3543d9..a9ebc7c8f8d 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1466,6 +1466,7 @@ + diff --git a/openapi.json b/openapi.json index ca5b2b566f7..85ad75e042a 100644 --- a/openapi.json +++ b/openapi.json @@ -2223,6 +2223,10 @@ "type": "integer", "format": "int64" }, + "default_days": { + "type": "integer", + "format": "int64" + }, "enforced": { "type": "boolean" }