Explorar el Código

Merge pull request #25320 from nextcloud/bugfix/noid/save-fed-share-expiration

Julius Härtl hace 3 años
padre
commit
1c35b3801e

+ 13 - 3
apps/federatedfilesharing/lib/FederatedShareProvider.php

@@ -173,6 +173,7 @@ class FederatedShareProvider implements IShareProvider {
 		$permissions = $share->getPermissions();
 		$sharedBy = $share->getSharedBy();
 		$shareType = $share->getShareType();
+		$expirationDate = $share->getExpirationDate();
 
 		if ($shareType === IShare::TYPE_REMOTE_GROUP &&
 			!$this->isOutgoingServer2serverGroupShareEnabled()
@@ -219,7 +220,7 @@ class FederatedShareProvider implements IShareProvider {
 		if ($remoteShare) {
 			try {
 				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
+				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType, $expirationDate);
 				$share->setId($shareId);
 				[$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
 				// remote share was create successfully if we get a valid token as return
@@ -264,7 +265,8 @@ class FederatedShareProvider implements IShareProvider {
 			$share->getShareOwner(),
 			$share->getPermissions(),
 			$token,
-			$share->getShareType()
+			$share->getShareType(),
+			$share->getExpirationDate()
 		);
 
 		$failure = false;
@@ -370,9 +372,10 @@ class FederatedShareProvider implements IShareProvider {
 	 * @param int $permissions
 	 * @param string $token
 	 * @param int $shareType
+	 * @param \DateTime $expirationDate
 	 * @return int
 	 */
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
+	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType, $expirationDate) {
 		$qb = $this->dbConnection->getQueryBuilder();
 		$qb->insert('share')
 			->setValue('share_type', $qb->createNamedParameter($shareType))
@@ -383,6 +386,7 @@ class FederatedShareProvider implements IShareProvider {
 			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
 			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
 			->setValue('permissions', $qb->createNamedParameter($permissions))
+			->setValue('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
 			->setValue('token', $qb->createNamedParameter($token))
 			->setValue('stime', $qb->createNamedParameter(time()));
 
@@ -412,6 +416,7 @@ class FederatedShareProvider implements IShareProvider {
 				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
 				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
 				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
+				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
 				->execute();
 
 		// send the updated permission to the owner/initiator, if they are not the same
@@ -910,6 +915,11 @@ class FederatedShareProvider implements IShareProvider {
 
 		$share->setProviderId($this->identifier());
 
+		if ($data['expiration'] !== null) {
+			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
+			$share->setExpirationDate($expiration);
+		}
+
 		return $share;
 	}
 

+ 22 - 7
apps/federatedfilesharing/tests/FederatedShareProviderTest.php

@@ -145,7 +145,17 @@ class FederatedShareProviderTest extends \Test\TestCase {
 		parent::tearDown();
 	}
 
-	public function testCreate() {
+	public function dataTestCreate() {
+		return [
+			[null, null],
+			[new \DateTime('2020-03-01T01:02:03'), '2020-03-01 01:02:03'],
+		];
+	}
+
+	/**
+	 * @dataProvider dataTestCreate
+	 */
+	public function testCreate($expirationDate, $expectedDataDate) {
 		$share = $this->shareManager->newShare();
 
 		/** @var File|MockObject $node */
@@ -158,6 +168,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
 			->setShareOwner('shareOwner')
 			->setPermissions(19)
 			->setShareType(IShare::TYPE_REMOTE)
+			->setExpirationDate($expirationDate)
 			->setNode($node);
 
 		$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -209,6 +220,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
 			'permissions' => 19,
 			'accepted' => 0,
 			'token' => 'token',
+			'expiration' => $expectedDataDate,
 		];
 		foreach (array_keys($expected) as $key) {
 			$this->assertEquals($expected[$key], $data[$key], "Assert that value for key '$key' is the same");
@@ -223,6 +235,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
 		$this->assertEquals(42, $share->getNodeId());
 		$this->assertEquals(19, $share->getPermissions());
 		$this->assertEquals('token', $share->getToken());
+		$this->assertEquals($expirationDate, $share->getExpirationDate());
 	}
 
 	public function testCreateCouldNotFindServer() {
@@ -442,10 +455,9 @@ class FederatedShareProviderTest extends \Test\TestCase {
 	}
 
 	/**
-	 * @dataProvider datatTestUpdate
-	 *
+	 * @dataProvider dataTestUpdate
 	 */
-	public function testUpdate($owner, $sharedBy) {
+	public function testUpdate($owner, $sharedBy, $expirationDate) {
 		$this->provider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider')
 			->setConstructorArgs(
 				[
@@ -478,6 +490,7 @@ class FederatedShareProviderTest extends \Test\TestCase {
 			->setShareOwner($owner)
 			->setPermissions(19)
 			->setShareType(IShare::TYPE_REMOTE)
+			->setExpirationDate(new \DateTime('2019-02-01T01:02:03'))
 			->setNode($node);
 
 		$this->tokenHandler->method('generateToken')->willReturn('token');
@@ -512,17 +525,19 @@ class FederatedShareProviderTest extends \Test\TestCase {
 		$share = $this->provider->create($share);
 
 		$share->setPermissions(1);
+		$share->setExpirationDate($expirationDate);
 		$this->provider->update($share);
 
 		$share = $this->provider->getShareById($share->getId());
 
 		$this->assertEquals(1, $share->getPermissions());
+		$this->assertEquals($expirationDate, $share->getExpirationDate());
 	}
 
-	public function datatTestUpdate() {
+	public function dataTestUpdate() {
 		return [
-			['sharedBy', 'shareOwner'],
-			['shareOwner', 'shareOwner']
+			['sharedBy', 'shareOwner', new \DateTime('2020-03-01T01:02:03')],
+			['shareOwner', 'shareOwner', null],
 		];
 	}
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
apps/files_sharing/js/dist/files_sharing_tab.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
apps/files_sharing/js/dist/files_sharing_tab.js.map


+ 11 - 1
apps/files_sharing/lib/Capabilities.php

@@ -86,6 +86,13 @@ class Capabilities implements ICapability {
 					$public['expire_date_internal']['enforced'] = $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
 				}
 
+				$public['expire_date_remote'] = [];
+				$public['expire_date_remote']['enabled'] = $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
+				if ($public['expire_date_remote']['enabled']) {
+					$public['expire_date_remote']['days'] = $this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
+					$public['expire_date_remote']['enforced'] = $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
+				}
+
 				$public['send_mail'] = $this->config->getAppValue('core', 'shareapi_allow_public_notification', 'no') === 'yes';
 				$public['upload'] = $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
 				$public['upload_files_drop'] = $public['upload'];
@@ -111,7 +118,10 @@ class Capabilities implements ICapability {
 		$res['federation'] = [
 			'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes',
 			'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes',
-			'expire_date' => ['enabled' => true]
+			// old bogus one, expire_date was not working before, keeping for compatibility
+			'expire_date' => ['enabled' => true],
+			// the real deal, signifies that expiration date can be set on federated shares
+			'expire_date_supported' => ['enabled' => true],
 		];
 
 		// Sharee searches

+ 24 - 0
apps/files_sharing/lib/Controller/ShareAPIController.php

@@ -587,15 +587,39 @@ class ShareAPIController extends OCSController {
 				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
 			}
 
+			if ($shareWith === null) {
+				throw new OCSNotFoundException($this->l->t('Please specify a valid federated user id'));
+			}
+
 			$share->setSharedWith($shareWith);
 			$share->setPermissions($permissions);
+			if ($expireDate !== '') {
+				try {
+					$expireDate = $this->parseDate($expireDate);
+					$share->setExpirationDate($expireDate);
+				} catch (\Exception $e) {
+					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
+				}
+			}
 		} elseif ($shareType === IShare::TYPE_REMOTE_GROUP) {
 			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
 				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
 			}
 
+			if ($shareWith === null) {
+				throw new OCSNotFoundException($this->l->t('Please specify a valid federated group id'));
+			}
+
 			$share->setSharedWith($shareWith);
 			$share->setPermissions($permissions);
+			if ($expireDate !== '') {
+				try {
+					$expireDate = $this->parseDate($expireDate);
+					$share->setExpirationDate($expireDate);
+				} catch (\Exception $e) {
+					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
+				}
+			}
 		} elseif ($shareType === IShare::TYPE_CIRCLE) {
 			if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
 				throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));

+ 11 - 12
apps/files_sharing/src/components/SharingEntry.vue

@@ -84,16 +84,14 @@
 				</ActionCheckbox>
 
 				<!-- expiration date -->
-				<ActionCheckbox
-					v-if="canHaveExpirationDate"
-					:checked.sync="hasExpirationDate"
+				<ActionCheckbox :checked.sync="hasExpirationDate"
 					:disabled="config.isDefaultInternalExpireDateEnforced || saving"
 					@uncheck="onExpirationDisable">
 					{{ config.isDefaultInternalExpireDateEnforced
 						? t('files_sharing', 'Expiration date enforced')
 						: t('files_sharing', 'Set expiration date') }}
 				</ActionCheckbox>
-				<ActionInput v-if="canHaveExpirationDate && hasExpirationDate"
+				<ActionInput v-if="hasExpirationDate"
 					ref="expireDate"
 					v-tooltip.auto="{
 						content: errors.expireDate,
@@ -224,14 +222,10 @@ export default {
 		},
 
 		canHaveNote() {
-			return !this.isRemoteShare
-		},
-
-		canHaveExpirationDate() {
-			return !this.isRemoteShare
+			return !this.isRemote
 		},
 
-		isRemoteShare() {
+		isRemote() {
 			return this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE
 				|| this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP
 		},
@@ -358,8 +352,13 @@ export default {
 		},
 
 		dateMaxEnforced() {
-			return this.config.isDefaultInternalExpireDateEnforced
-				&& moment().add(1 + this.config.defaultInternalExpireDate, 'days')
+			if (!this.isRemote) {
+				return this.config.isDefaultInternalExpireDateEnforced
+					&& moment().add(1 + this.config.defaultInternalExpireDate, 'days')
+			} else {
+				return this.config.isDefaultRemoteExpireDateEnforced
+					&& moment().add(1 + this.config.defaultRemoteExpireDate, 'days')
+			}
 		},
 
 		/**

+ 40 - 0
apps/files_sharing/src/services/ConfigService.js

@@ -95,6 +95,24 @@ export default class Config {
 		return expireDateString
 	}
 
+	/**
+	 * Get the default remote expiration date as string
+	 *
+	 * @returns {string}
+	 * @readonly
+	 * @memberof Config
+	 */
+	get defaultRemoteExpirationDateString() {
+		let expireDateString = ''
+		if (this.isDefaultRemoteExpireDateEnabled) {
+			const date = window.moment.utc()
+			const expireAfterDays = this.defaultRemoteExpireDate
+			date.add(expireAfterDays, 'days')
+			expireDateString = date.format('YYYY-MM-DD')
+		}
+		return expireDateString
+	}
+
 	/**
 	 * Are link shares password-enforced ?
 	 *
@@ -150,6 +168,17 @@ export default class Config {
 		return OC.appConfig.core.defaultInternalExpireDateEnforced === true
 	}
 
+	/**
+	 * Is remote shares expiration enforced ?
+	 *
+	 * @returns {boolean}
+	 * @readonly
+	 * @memberof Config
+	 */
+	get isDefaultRemoteExpireDateEnforced() {
+		return OC.appConfig.core.defaultRemoteExpireDateEnforced === true
+	}
+
 	/**
 	 * Is there a default expiration date for new internal shares ?
 	 *
@@ -209,6 +238,17 @@ export default class Config {
 		return OC.appConfig.core.defaultInternalExpireDate
 	}
 
+	/**
+	 * Get the default days to remote shares expiration
+	 *
+	 * @returns {int}
+	 * @readonly
+	 * @memberof Config
+	 */
+	get defaultRemoteExpireDate() {
+		return OC.appConfig.core.defaultRemoteExpireDate
+	}
+
 	/**
 	 * Is resharing allowed ?
 	 *

+ 7 - 0
apps/files_sharing/tests/CapabilitiesTest.php

@@ -285,4 +285,11 @@ class CapabilitiesTest extends \Test\TestCase {
 		$this->assertArrayHasKey('federation', $result);
 		$this->assertFalse($result['federation']['outgoing']);
 	}
+
+	public function testFederatedSharingExpirationDate() {
+		$result = $this->getResults([]);
+		$this->assertArrayHasKey('federation', $result);
+		$this->assertEquals(['enabled' => true], $result['federation']['expire_date']);
+		$this->assertEquals(['enabled' => true], $result['federation']['expire_date_supported']);
+	}
 }

+ 191 - 1
apps/files_sharing/tests/Controller/ShareAPIControllerTest.php

@@ -995,6 +995,7 @@ class ShareAPIControllerTest extends TestCase {
 			->setSharedBy('initiator')
 			->setShareOwner('currentUser')
 			->setPermissions(\OCP\Constants::PERMISSION_READ)
+			->setExpirationDate(new \DateTime('2000-01-01T01:02:03'))
 			->setNode($file1)
 			->setId(815);
 
@@ -1009,6 +1010,7 @@ class ShareAPIControllerTest extends TestCase {
 			->setSharedBy('initiator')
 			->setShareOwner('currentUser')
 			->setPermissions(\OCP\Constants::PERMISSION_READ)
+			->setExpirationDate(new \DateTime('2000-01-02T01:02:03'))
 			->setNode($file1)
 			->setId(816);
 
@@ -2173,6 +2175,146 @@ class ShareAPIControllerTest extends TestCase {
 		$ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, 'a1b2d3');
 	}
 
+	public function testCreateShareRemote() {
+		$share = $this->newShare();
+		$this->shareManager->method('newShare')->willReturn($share);
+
+		/** @var \OCA\Files_Sharing\Controller\ShareAPIController $ocs */
+		$ocs = $this->getMockBuilder(ShareAPIController::class)
+			->setConstructorArgs([
+				$this->appName,
+				$this->request,
+				$this->shareManager,
+				$this->groupManager,
+				$this->userManager,
+				$this->rootFolder,
+				$this->urlGenerator,
+				$this->currentUser,
+				$this->l,
+				$this->config,
+				$this->appManager,
+				$this->serverContainer,
+				$this->userStatusManager,
+				$this->previewManager,
+			])->setMethods(['formatShare'])
+			->getMock();
+
+		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
+		$this->rootFolder->expects($this->once())
+				->method('getUserFolder')
+				->with('currentUser')
+				->willReturn($userFolder);
+
+		$path = $this->getMockBuilder(File::class)->getMock();
+		$storage = $this->createMock(Storage::class);
+		$storage->method('instanceOfStorage')
+			->with('OCA\Files_Sharing\External\Storage')
+			->willReturn(false);
+		$path->method('getStorage')->willReturn($storage);
+		$userFolder->expects($this->once())
+				->method('get')
+				->with('valid-path')
+				->willReturn($path);
+
+		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
+
+		$path->expects($this->once())
+			->method('lock')
+			->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
+
+		$this->shareManager->method('createShare')
+			->with($this->callback(function (\OCP\Share\IShare $share) use ($path) {
+				return $share->getNode() === $path &&
+					$share->getPermissions() === (
+						\OCP\Constants::PERMISSION_ALL &
+						~\OCP\Constants::PERMISSION_DELETE &
+						~\OCP\Constants::PERMISSION_CREATE
+					) &&
+					$share->getShareType() === IShare::TYPE_REMOTE &&
+					$share->getSharedWith() === 'user@example.org' &&
+					$share->getSharedBy() === 'currentUser';
+			}))
+			->willReturnArgument(0);
+
+		$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
+
+		$expected = new DataResponse([]);
+		$result = $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, IShare::TYPE_REMOTE, 'user@example.org');
+
+		$this->assertInstanceOf(get_class($expected), $result);
+		$this->assertEquals($expected->getData(), $result->getData());
+	}
+
+	public function testCreateShareRemoteGroup() {
+		$share = $this->newShare();
+		$this->shareManager->method('newShare')->willReturn($share);
+
+		/** @var \OCA\Files_Sharing\Controller\ShareAPIController $ocs */
+		$ocs = $this->getMockBuilder(ShareAPIController::class)
+			->setConstructorArgs([
+				$this->appName,
+				$this->request,
+				$this->shareManager,
+				$this->groupManager,
+				$this->userManager,
+				$this->rootFolder,
+				$this->urlGenerator,
+				$this->currentUser,
+				$this->l,
+				$this->config,
+				$this->appManager,
+				$this->serverContainer,
+				$this->userStatusManager,
+				$this->previewManager,
+			])->setMethods(['formatShare'])
+			->getMock();
+
+		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
+		$this->rootFolder->expects($this->once())
+				->method('getUserFolder')
+				->with('currentUser')
+				->willReturn($userFolder);
+
+		$path = $this->getMockBuilder(File::class)->getMock();
+		$storage = $this->createMock(Storage::class);
+		$storage->method('instanceOfStorage')
+			->with('OCA\Files_Sharing\External\Storage')
+			->willReturn(false);
+		$path->method('getStorage')->willReturn($storage);
+		$userFolder->expects($this->once())
+				->method('get')
+				->with('valid-path')
+				->willReturn($path);
+
+		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
+
+		$path->expects($this->once())
+			->method('lock')
+			->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
+
+		$this->shareManager->method('createShare')
+			->with($this->callback(function (\OCP\Share\IShare $share) use ($path) {
+				return $share->getNode() === $path &&
+					$share->getPermissions() === (
+						\OCP\Constants::PERMISSION_ALL &
+						~\OCP\Constants::PERMISSION_DELETE &
+						~\OCP\Constants::PERMISSION_CREATE
+					) &&
+					$share->getShareType() === IShare::TYPE_REMOTE_GROUP &&
+					$share->getSharedWith() === 'group@example.org' &&
+					$share->getSharedBy() === 'currentUser';
+			}))
+			->willReturnArgument(0);
+
+		$this->shareManager->method('outgoingServer2ServerGroupSharesAllowed')->willReturn(true);
+
+		$expected = new DataResponse([]);
+		$result = $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, IShare::TYPE_REMOTE_GROUP, 'group@example.org');
+
+		$this->assertInstanceOf(get_class($expected), $result);
+		$this->assertEquals($expected->getData(), $result->getData());
+	}
+
 	public function testCreateShareRoom() {
 		$ocs = $this->mockFormatShare();
 
@@ -3841,6 +3983,7 @@ class ShareAPIControllerTest extends TestCase {
 			->setPermissions(\OCP\Constants::PERMISSION_READ)
 			->setNode($folder)
 			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+			->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
 			->setTarget('myTarget')
 			->setNote('personal note')
 			->setId(42);
@@ -3854,7 +3997,54 @@ class ShareAPIControllerTest extends TestCase {
 				'permissions' => 1,
 				'stime' => 946684862,
 				'parent' => null,
-				'expiration' => null,
+				'expiration' => '2001-02-03 00:00:00',
+				'token' => null,
+				'uid_file_owner' => 'owner',
+				'displayname_file_owner' => 'owner',
+				'note' => 'personal note',
+				'label' => null,
+				'path' => 'folder',
+				'item_type' => 'folder',
+				'storage_id' => 'storageId',
+				'storage' => 100,
+				'item_source' => 2,
+				'file_source' => 2,
+				'file_parent' => 1,
+				'file_target' => 'myTarget',
+				'share_with' => 'user@server.com',
+				'share_with_displayname' => 'foobar',
+				'mail_send' => 0,
+				'mimetype' => 'myFolderMimeType',
+				'has_preview' => false,
+				'hide_download' => 0,
+				'can_edit' => false,
+				'can_delete' => false,
+			], $share, [], false
+		];
+
+		$share = \OC::$server->getShareManager()->newShare();
+		$share->setShareType(IShare::TYPE_REMOTE_GROUP)
+			->setSharedBy('initiator')
+			->setSharedWith('user@server.com')
+			->setShareOwner('owner')
+			->setPermissions(\OCP\Constants::PERMISSION_READ)
+			->setNode($folder)
+			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+			->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
+			->setTarget('myTarget')
+			->setNote('personal note')
+			->setId(42);
+
+		$result[] = [
+			[
+				'id' => 42,
+				'share_type' => IShare::TYPE_REMOTE_GROUP,
+				'uid_owner' => 'initiator',
+				'displayname_owner' => 'initiator',
+				'permissions' => 1,
+				'stime' => 946684862,
+				'parent' => null,
+				'expiration' => '2001-02-03 00:00:00',
 				'token' => null,
 				'uid_file_owner' => 'owner',
 				'displayname_file_owner' => 'owner',

+ 4 - 0
apps/settings/js/admin.js

@@ -90,6 +90,10 @@ window.addEventListener('DOMContentLoaded', function(){
 		$("#setDefaultInternalExpireDate").toggleClass('hidden', !this.checked);
 	});
 
+	$('#shareapiDefaultRemoteExpireDate').change(function() {
+		$("#setDefaultRemoteExpireDate").toggleClass('hidden', !this.checked);
+	});
+
 	$('#publicShareDisclaimer').change(function() {
 		$("#publicShareDisclaimerText").toggleClass('hidden', !this.checked);
 		if(!this.checked) {

+ 3 - 0
apps/settings/lib/Settings/Admin/Sharing.php

@@ -90,6 +90,9 @@ class Sharing implements ISettings {
 			'shareDefaultInternalExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no'),
 			'shareInternalExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7'),
 			'shareInternalEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no'),
+			'shareDefaultRemoteExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no'),
+			'shareRemoteExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7'),
+			'shareRemoteEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no'),
 		];
 
 		return new TemplateResponse('settings', 'settings/admin/sharing', $parameters, '');

+ 23 - 0
apps/settings/templates/settings/admin/sharing.php

@@ -63,6 +63,29 @@
 		<label for="shareapiInternalEnforceExpireDate"><?php p($l->t('Enforce expiration date'));?></label><br/>
 	</p>
 
+	<p id="remoteShareSettings" class="indent <?php if ($_['shareAPIEnabled'] === 'no') {
+	p('hidden');
+} ?>">
+		<input type="checkbox" name="shareapi_default_remote_expire_date" id="shareapiDefaultRemoteExpireDate" class="checkbox"
+			   value="1" <?php if ($_['shareDefaultRemoteExpireDateSet'] === 'yes') {
+	print_unescaped('checked="checked"');
+} ?> />
+		<label for="shareapiDefaultRemoteExpireDate"><?php p($l->t('Set default expiration date for shares to other servers'));?></label><br/>
+	</p>
+	<p id="setDefaultRemoteExpireDate" class="double-indent <?php if ($_['shareDefaultRemoteExpireDateSet'] === 'no' || $_['shareAPIEnabled'] === 'no') {
+	p('hidden');
+}?>">
+		<?php p($l->t('Expire after ')); ?>
+		<input type="text" name='shareapi_remote_expire_after_n_days' id="shareapiRemoteExpireAfterNDays" placeholder="<?php p('7')?>"
+			   value='<?php p($_['shareRemoteExpireAfterNDays']) ?>' />
+		<?php p($l->t('days')); ?>
+		<input type="checkbox" name="shareapi_enforce_remote_expire_date" id="shareapiRemoteEnforceExpireDate" class="checkbox"
+			   value="1" <?php if ($_['shareRemoteEnforceExpireDate'] === 'yes') {
+	print_unescaped('checked="checked"');
+} ?> />
+		<label for="shareapiRemoteEnforceExpireDate"><?php p($l->t('Enforce expiration date'));?></label><br/>
+	</p>
+
 	<p class="<?php if ($_['shareAPIEnabled'] === 'no') {
 	p('hidden');
 }?>">

+ 12 - 0
apps/settings/tests/Settings/Admin/SharingTest.php

@@ -86,6 +86,9 @@ class SharingTest extends TestCase {
 				['core', 'shareapi_default_internal_expire_date', 'no', 'no'],
 				['core', 'shareapi_internal_expire_after_n_days', '7', '7'],
 				['core', 'shareapi_enforce_internal_expire_date', 'no', 'no'],
+				['core', 'shareapi_default_remote_expire_date', 'no', 'no'],
+				['core', 'shareapi_remote_expire_after_n_days', '7', '7'],
+				['core', 'shareapi_enforce_remote_expire_date', 'no', 'no'],
 			]);
 
 		$expected = new TemplateResponse(
@@ -115,6 +118,9 @@ class SharingTest extends TestCase {
 				'shareDefaultInternalExpireDateSet' => 'no',
 				'shareInternalExpireAfterNDays' => '7',
 				'shareInternalEnforceExpireDate' => 'no',
+				'shareDefaultRemoteExpireDateSet' => 'no',
+				'shareRemoteExpireAfterNDays' => '7',
+				'shareRemoteEnforceExpireDate' => 'no',
 			],
 			''
 		);
@@ -146,6 +152,9 @@ class SharingTest extends TestCase {
 				['core', 'shareapi_default_internal_expire_date', 'no', 'no'],
 				['core', 'shareapi_internal_expire_after_n_days', '7', '7'],
 				['core', 'shareapi_enforce_internal_expire_date', 'no', 'no'],
+				['core', 'shareapi_default_remote_expire_date', 'no', 'no'],
+				['core', 'shareapi_remote_expire_after_n_days', '7', '7'],
+				['core', 'shareapi_enforce_remote_expire_date', 'no', 'no'],
 			]);
 
 		$expected = new TemplateResponse(
@@ -175,6 +184,9 @@ class SharingTest extends TestCase {
 				'shareDefaultInternalExpireDateSet' => 'no',
 				'shareInternalExpireAfterNDays' => '7',
 				'shareInternalEnforceExpireDate' => 'no',
+				'shareDefaultRemoteExpireDateSet' => 'no',
+				'shareRemoteExpireAfterNDays' => '7',
+				'shareRemoteEnforceExpireDate' => 'no',
 			],
 			''
 		);

+ 57 - 9
lib/private/Share20/Manager.php

@@ -385,6 +385,8 @@ class Manager implements IManager {
 	 * @throws \Exception
 	 */
 	protected function validateExpirationDateInternal(IShare $share) {
+		$isRemote = $share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP;
+
 		$expirationDate = $share->getExpirationDate();
 
 		if ($expirationDate !== null) {
@@ -407,28 +409,39 @@ class Manager implements IManager {
 			// This is a new share
 		}
 
-		if ($fullId === null && $expirationDate === null && $this->shareApiInternalDefaultExpireDate()) {
+		if ($isRemote) {
+			$defaultExpireDate = $this->shareApiRemoteDefaultExpireDate();
+			$defaultExpireDays = $this->shareApiRemoteDefaultExpireDays();
+			$configProp = 'remote_defaultExpDays';
+			$isEnforced = $this->shareApiRemoteDefaultExpireDateEnforced();
+		} else {
+			$defaultExpireDate = $this->shareApiInternalDefaultExpireDate();
+			$defaultExpireDays = $this->shareApiInternalDefaultExpireDays();
+			$configProp = 'internal_defaultExpDays';
+			$isEnforced = $this->shareApiInternalDefaultExpireDateEnforced();
+		}
+		if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
 			$expirationDate = new \DateTime();
 			$expirationDate->setTime(0,0,0);
 
-			$days = (int)$this->config->getAppValue('core', 'internal_defaultExpDays', (string)$this->shareApiInternalDefaultExpireDays());
-			if ($days > $this->shareApiInternalDefaultExpireDays()) {
-				$days = $this->shareApiInternalDefaultExpireDays();
+			$days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
+			if ($days > $defaultExpireDays) {
+				$days = $defaultExpireDays;
 			}
 			$expirationDate->add(new \DateInterval('P'.$days.'D'));
 		}
 
 		// If we enforce the expiration date check that is does not exceed
-		if ($this->shareApiInternalDefaultExpireDateEnforced()) {
+		if ($isEnforced) {
 			if ($expirationDate === null) {
 				throw new \InvalidArgumentException('Expiration date is enforced');
 			}
 
 			$date = new \DateTime();
 			$date->setTime(0, 0, 0);
-			$date->add(new \DateInterval('P' . $this->shareApiInternalDefaultExpireDays() . 'D'));
+			$date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
 			if ($date < $expirationDate) {
-				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiInternalDefaultExpireDays()]);
+				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$defaultExpireDays]);
 				throw new GenericShareException($message, $message, 404);
 			}
 		}
@@ -751,6 +764,9 @@ class Manager implements IManager {
 
 				// Verify the expiration date
 				$share = $this->validateExpirationDateInternal($share);
+			} elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
+				//Verify the expiration date
+				$share = $this->validateExpirationDateInternal($share);
 			} elseif ($share->getShareType() === IShare::TYPE_LINK
 				|| $share->getShareType() === IShare::TYPE_EMAIL) {
 				$this->linkCreateChecks($share);
@@ -999,7 +1015,7 @@ class Manager implements IManager {
 			if (empty($plainTextPassword) && $share->getSendPasswordByTalk()) {
 				throw new \InvalidArgumentException('Can’t enable sending the password by Talk with an empty password');
 			}
-	
+
 			/**
 			 * If we're in a mail share, we need to force a password change
 			 * as either the user is not aware of the password or is already (received by mail)
@@ -1019,6 +1035,12 @@ class Manager implements IManager {
 				$this->validateExpirationDateLink($share);
 				$expirationDateUpdated = true;
 			}
+		} elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
+			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
+				//Verify the expiration date
+				$this->validateExpirationDateInternal($share);
+				$expirationDateUpdated = true;
+			}
 		}
 
 		$this->pathCreateChecks($share->getNode());
@@ -1783,9 +1805,18 @@ class Manager implements IManager {
 		return $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes';
 	}
 
+	/**
+	 * Is default remote expire date enabled
+	 *
+	 * @return bool
+	 */
+	public function shareApiRemoteDefaultExpireDate(): bool {
+		return $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
+	}
+
 	/**
 	 * Is default expire date enforced
-	 *`
+	 *
 	 * @return bool
 	 */
 	public function shareApiInternalDefaultExpireDateEnforced(): bool {
@@ -1793,6 +1824,15 @@ class Manager implements IManager {
 			$this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
 	}
 
+	/**
+	 * Is default expire date enforced for remote shares
+	 *
+	 * @return bool
+	 */
+	public function shareApiRemoteDefaultExpireDateEnforced(): bool {
+		return $this->shareApiRemoteDefaultExpireDate() &&
+			$this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
+	}
 
 	/**
 	 * Number of default expire days
@@ -1802,6 +1842,14 @@ class Manager implements IManager {
 		return (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7');
 	}
 
+	/**
+	 * Number of default expire days for remote shares
+	 * @return int
+	 */
+	public function shareApiRemoteDefaultExpireDays(): int {
+		return (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
+	}
+
 	/**
 	 * Allow public upload on link shares
 	 *

+ 10 - 0
lib/private/Template/JSConfigHelper.php

@@ -165,6 +165,13 @@ class JSConfigHelper {
 			$defaultInternalExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
 		}
 
+		$defaultRemoteExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
+		$defaultRemoteExpireDate = $defaultRemoteExpireDateEnforced = null;
+		if ($defaultRemoteExpireDateEnabled) {
+			$defaultRemoteExpireDate = (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
+			$defaultRemoteExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
+		}
+
 		$countOfDataLocation = 0;
 		$dataLocation = str_replace(\OC::$SERVERROOT . '/', '', $this->config->getSystemValue('datadirectory', ''), $countOfDataLocation);
 		if ($countOfDataLocation !== 1 || $uid === null || !$this->groupManager->isAdmin($uid)) {
@@ -278,6 +285,9 @@ class JSConfigHelper {
 					'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled,
 					'defaultInternalExpireDate' => $defaultInternalExpireDate,
 					'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced,
+					'defaultRemoteExpireDateEnabled' => $defaultRemoteExpireDateEnabled,
+					'defaultRemoteExpireDate' => $defaultRemoteExpireDate,
+					'defaultRemoteExpireDateEnforced' => $defaultRemoteExpireDateEnforced,
 				]
 			]),
 			"_theme" => json_encode([

+ 207 - 70
tests/lib/Share20/ManagerTest.php

@@ -772,7 +772,14 @@ class ManagerTest extends \Test\TestCase {
 		self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
 	}
 
-	public function testValidateExpirationDateInternalInPast() {
+	public function validateExpirationDateInternalProvider() {
+		return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]];
+	}
+
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalInPast($shareType) {
 		$this->expectException(\OCP\Share\Exceptions\GenericShareException::class);
 		$this->expectExceptionMessage('Expiration date is in the past');
 
@@ -781,51 +788,88 @@ class ManagerTest extends \Test\TestCase {
 		$past->sub(new \DateInterval('P1D'));
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($past);
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 	}
 
-	public function testValidateExpirationDateInternalEnforceButNotSet() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceButNotSet($shareType) {
 		$this->expectException(\InvalidArgumentException::class);
 		$this->expectExceptionMessage('Expiration date is enforced');
 
 		$share = $this->manager->newShare();
 		$share->setProviderId('foo')->setId('bar');
-
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-			]);
+		$share->setShareType($shareType);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+				]);
+		}
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 	}
 
-	public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType) {
 		$share = $this->manager->newShare();
 		$share->setProviderId('foo')->setId('bar');
+		$share->setShareType($shareType);
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+				]);
+		}
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 
 		$this->assertNull($share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalEnforceButNotSetNewShare() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType) {
 		$share = $this->manager->newShare();
-
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'internal_defaultExpDays', '3', '3'],
-			]);
+		$share->setShareType($shareType);
+
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'internal_defaultExpDays', '3', '3'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'remote_defaultExpDays', '3', '3'],
+				]);
+		}
 
 		$expected = new \DateTime();
 		$expected->setTime(0,0,0);
@@ -837,16 +881,30 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType) {
 		$share = $this->manager->newShare();
-
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'internal_defaultExpDays', '3', '1'],
-			]);
+		$share->setShareType($shareType);
+
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'internal_defaultExpDays', '3', '1'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'remote_defaultExpDays', '3', '1'],
+				]);
+		}
 
 		$expected = new \DateTime();
 		$expected->setTime(0,0,0);
@@ -858,7 +916,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalEnforceTooFarIntoFuture() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType) {
 		$this->expectException(\OCP\Share\Exceptions\GenericShareException::class);
 		$this->expectExceptionMessage('Can’t set expiration date more than 3 days in the future');
 
@@ -866,19 +927,32 @@ class ManagerTest extends \Test\TestCase {
 		$future->add(new \DateInterval('P7D'));
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($future);
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+				]);
+		}
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 	}
 
-	public function testValidateExpirationDateInternalEnforceValid() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalEnforceValid($shareType) {
 		$future = new \DateTime();
 		$future->add(new \DateInterval('P2D'));
 		$future->setTime(1,2,3);
@@ -887,14 +961,24 @@ class ManagerTest extends \Test\TestCase {
 		$expected->setTime(0,0,0);
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($future);
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+				]);
+		}
 
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
 		\OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
@@ -907,7 +991,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalNoDefault() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalNoDefault($shareType) {
 		$date = new \DateTime();
 		$date->add(new \DateInterval('P5D'));
 		$date->setTime(1,2,3);
@@ -916,6 +1003,7 @@ class ManagerTest extends \Test\TestCase {
 		$expected->setTime(0,0,0);
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($date);
 
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
@@ -929,7 +1017,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalNoDateNoDefault() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalNoDateNoDefault($shareType) {
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
 		\OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
 		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
@@ -937,6 +1028,7 @@ class ManagerTest extends \Test\TestCase {
 		}));
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setPassword('password');
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
@@ -944,19 +1036,32 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertNull($share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalNoDateDefault() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalNoDateDefault($shareType) {
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 
 		$expected = new \DateTime();
 		$expected->add(new \DateInterval('P3D'));
 		$expected->setTime(0,0,0);
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'internal_defaultExpDays', '3', '3'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'internal_defaultExpDays', '3', '3'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'remote_defaultExpDays', '3', '3'],
+				]);
+		}
 
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
 		\OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
@@ -969,7 +1074,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalDefault() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalDefault($shareType) {
 		$future = new \DateTime();
 		$future->add(new \DateInterval('P5D'));
 		$future->setTime(1,2,3);
@@ -978,14 +1086,24 @@ class ManagerTest extends \Test\TestCase {
 		$expected->setTime(0,0,0);
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($future);
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
-				['core', 'internal_defaultExpDays', '3', '1'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
+					['core', 'internal_defaultExpDays', '3', '1'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
+					['core', 'remote_defaultExpDays', '3', '1'],
+				]);
+		}
 
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
 		\OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
@@ -998,7 +1116,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($expected, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalHookModification() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalHookModification($shareType) {
 		$nextWeek = new \DateTime();
 		$nextWeek->add(new \DateInterval('P7D'));
 		$nextWeek->setTime(0,0,0);
@@ -1012,6 +1133,7 @@ class ManagerTest extends \Test\TestCase {
 		});
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($nextWeek);
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
@@ -1020,7 +1142,10 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertEquals($save, $share->getExpirationDate());
 	}
 
-	public function testValidateExpirationDateInternalHookException() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalHookException($shareType) {
 		$this->expectException(\Exception::class);
 		$this->expectExceptionMessage('Invalid date!');
 
@@ -1029,6 +1154,7 @@ class ManagerTest extends \Test\TestCase {
 		$nextWeek->setTime(0,0,0);
 
 		$share = $this->manager->newShare();
+		$share->setShareType($shareType);
 		$share->setExpirationDate($nextWeek);
 
 		$hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock();
@@ -1041,16 +1167,27 @@ class ManagerTest extends \Test\TestCase {
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 	}
 
-	public function testValidateExpirationDateInternalExistingShareNoDefault() {
+	/**
+	 * @dataProvider validateExpirationDateInternalProvider
+	 */
+	public function testValidateExpirationDateInternalExistingShareNoDefault($shareType) {
 		$share = $this->manager->newShare();
-
+		$share->setShareType($shareType);
 		$share->setId('42')->setProviderId('foo');
 
-		$this->config->method('getAppValue')
-			->willReturnMap([
-				['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
-				['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
-			]);
+		if ($shareType === IShare::TYPE_USER) {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
+					['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
+				]);
+		} else {
+			$this->config->method('getAppValue')
+				->willReturnMap([
+					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
+					['core', 'shareapi_remote_expire_after_n_days', '7', '6'],
+				]);
+		}
 
 		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio