aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorskjnldsv <skjnldsv@protonmail.com>2024-07-09 15:38:33 +0200
committerJohn Molakvoæ <skjnldsv@users.noreply.github.com>2024-07-12 20:14:30 +0200
commit967b3848e0e2eeb7ca5447599769fd9fbf825069 (patch)
tree2711b6de5aa29c96d30c79de16f29fd72aa1396e /apps
parentbc5839e5b5e2192ed7d2dd2173ab5ca72b1d8ebc (diff)
downloadnextcloud-server-967b3848e0e2eeb7ca5447599769fd9fbf825069.tar.gz
nextcloud-server-967b3848e0e2eeb7ca5447599769fd9fbf825069.zip
fix(files_sharing): phpunit & openapi fixes
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php10
-rw-r--r--apps/files_sharing/openapi.json183
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog.vue18
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogDatePassword.vue5
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogFinish.vue2
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogIntro.vue2
-rw-r--r--apps/files_sharing/src/components/SharingEntryLink.vue2
-rw-r--r--apps/files_sharing/src/components/SharingInput.vue1
-rw-r--r--apps/files_sharing/src/models/Share.js1
-rw-r--r--apps/files_sharing/src/services/ConfigService.ts167
-rw-r--r--apps/files_sharing/tests/ApiTest.php6
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php58
-rw-r--r--apps/files_sharing/tests/MountProviderTest.php20
-rw-r--r--apps/sharebymail/lib/ShareByMailProvider.php47
-rw-r--r--apps/sharebymail/tests/ShareByMailProviderTest.php564
15 files changed, 774 insertions, 312 deletions
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 0936d60b9cc..273dd30f7ef 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -2065,8 +2065,14 @@ class ShareAPIController extends OCSController {
/**
* Send a mail notification again for a share.
* The mail_send option must be enabled for the given share.
- * @param string $id
+ * @param string $id the share ID
* @param string $password optional, the password to check against. Necessary for password protected shares.
+ * @throws OCSNotFoundException Share not found
+ * @throws OCSForbiddenException You are not allowed to send mail notifications
+ * @throws OCSBadRequestException Invalid request or wrong password
+ * @throws OCSException Error while sending mail notification
+ * @return DataResponse<Http::STATUS_OK, array<empty>, array{}>
+ * 200: The email notification was sent successfully
*/
#[NoAdminRequired]
#[UserRateLimit(limit: 5, period: 120)]
@@ -2110,7 +2116,7 @@ class ShareAPIController extends OCSController {
}
$provider->sendMailNotification($share);
- return new DataResponse(['message' => 'ok']);
+ return new DataResponse();
} catch(OCSBadRequestException $e) {
throw $e;
} catch (Exception $e) {
diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json
index 65beb9121b8..8669fdcc8e1 100644
--- a/apps/files_sharing/openapi.json
+++ b/apps/files_sharing/openapi.json
@@ -1755,6 +1755,15 @@
"type": "string",
"nullable": true,
"description": "Additional attributes for the share"
+ },
+ "sendMail": {
+ "type": "string",
+ "nullable": true,
+ "enum": [
+ "false",
+ "true"
+ ],
+ "description": "Send a mail to the recipient"
}
}
}
@@ -2256,6 +2265,11 @@
"type": "string",
"nullable": true,
"description": "New additional attributes"
+ },
+ "sendMail": {
+ "type": "string",
+ "nullable": true,
+ "description": "if the share should be send by mail.\n Considering the share already exists, no mail will be send after the share is updated.\n \t\t\t\t You will have to use the sendMail action to send the mail."
}
}
}
@@ -2523,6 +2537,175 @@
}
}
},
+ "/ocs/v2.php/apps/files_sharing/api/v1/shares/{id}/send-email": {
+ "post": {
+ "operationId": "shareapi-send-share-email",
+ "summary": "Send a mail notification again for a share. The mail_send option must be enabled for the given share.",
+ "tags": [
+ "shareapi"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "password": {
+ "type": "string",
+ "default": "",
+ "description": "optional, the password to check against. Necessary for password protected shares."
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "the share ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "404": {
+ "description": "Share not found",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "You are not allowed to send mail notifications",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request or wrong password",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "The email notification was sent successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/{id}": {
"post": {
"operationId": "shareapi-accept-share",
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog.vue b/apps/files_sharing/src/components/NewFileRequestDialog.vue
index b0a969c25f1..6f5044d21e5 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog.vue
@@ -41,7 +41,7 @@
<FileRequestFinish v-if="share"
v-show="currentStep === STEP.LAST"
:emails="emails"
- :isShareByMailEnabled="isShareByMailEnabled"
+ :is-share-by-mail-enabled="isShareByMailEnabled"
:share="share"
@add-email="email => emails.push(email)"
@remove-email="onRemoveEmail" />
@@ -103,8 +103,9 @@
</template>
<script lang="ts">
+// eslint-disable-next-line n/no-extraneous-import
import type { AxiosError } from 'axios'
-import { Permission, type Folder, type Node } from '@nextcloud/files'
+import type { Folder, Node } from '@nextcloud/files'
import type { OCSResponse } from '@nextcloud/typings/ocs'
import type { PropType } from 'vue'
@@ -112,9 +113,10 @@ import { defineComponent } from 'vue'
import { emit } from '@nextcloud/event-bus'
import { generateOcsUrl } from '@nextcloud/router'
import { getCapabilities } from '@nextcloud/capabilities'
+import { Permission } from '@nextcloud/files'
+import { ShareType } from '@nextcloud/sharing'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
-import { Type } from '@nextcloud/sharing'
import axios from '@nextcloud/axios'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
@@ -170,7 +172,7 @@ export default defineComponent({
n: translatePlural,
t: translate,
- isShareByMailEnabled: getCapabilities()?.files_sharing?.sharebymail?.enabled === true
+ isShareByMailEnabled: getCapabilities()?.files_sharing?.sharebymail?.enabled === true,
}
},
@@ -254,9 +256,9 @@ export default defineComponent({
const shareUrl = generateOcsUrl('apps/files_sharing/api/v1/shares')
try {
const request = await axios.post<OCSResponse>(shareUrl, {
- shareType: Type.SHARE_TYPE_EMAIL,
+ shareType: ShareType.Email,
permissions: Permission.CREATE,
-
+
label: this.label,
path: this.destination,
note: this.note,
@@ -331,7 +333,7 @@ export default defineComponent({
}
},
- async sendEmails () {
+ async sendEmails() {
this.loading = true
// This should never happen™
@@ -358,7 +360,7 @@ export default defineComponent({
}
},
- onEmailSendError(error: AxiosError<OCSResponse>|any) {
+ onEmailSendError(error: AxiosError<OCSResponse>) {
const errorMessage = error.response?.data?.ocs?.meta?.message
showError(
errorMessage
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogDatePassword.vue b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogDatePassword.vue
index 1087fdd5a06..651f2a52efe 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogDatePassword.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogDatePassword.vue
@@ -37,7 +37,7 @@
:value="expirationDate"
name="expirationDate"
type="date"
- @update:value="$emit('update:expirationDate', $event)"/>
+ @update:value="$emit('update:expirationDate', $event)" />
</fieldset>
<!-- Password -->
@@ -96,7 +96,7 @@ import GeneratePassword from '../../utils/GeneratePassword'
const sharingConfig = new Config()
export default defineComponent({
- name: 'FileRequestDatePassword',
+ name: 'NewFileRequestDialogDatePassword',
components: {
IconPasswordGen,
@@ -207,7 +207,6 @@ export default defineComponent({
this.$emit('update:password', null)
},
-
async onGeneratePassword() {
await this.generatePassword()
this.showPassword()
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogFinish.vue b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogFinish.vue
index 423565f4d48..1fac6444a2a 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogFinish.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogFinish.vue
@@ -73,7 +73,7 @@ import IconCheck from 'vue-material-design-icons/Check.vue'
import IconClipboard from 'vue-material-design-icons/Clipboard.vue'
export default defineComponent({
- name: 'FileRequestFinish',
+ name: 'NewFileRequestDialogFinish',
components: {
IconCheck,
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogIntro.vue b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogIntro.vue
index 766fbc3fc22..858406b1fd0 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogIntro.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog/NewFileRequestDialogIntro.vue
@@ -73,7 +73,7 @@ import NcTextArea from '@nextcloud/vue/dist/Components/NcTextArea.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
export default defineComponent({
- name: 'FileRequestIntro',
+ name: 'NewFileRequestDialogIntro',
components: {
IconFolder,
diff --git a/apps/files_sharing/src/components/SharingEntryLink.vue b/apps/files_sharing/src/components/SharingEntryLink.vue
index e9b7ee44815..7fad50ebc95 100644
--- a/apps/files_sharing/src/components/SharingEntryLink.vue
+++ b/apps/files_sharing/src/components/SharingEntryLink.vue
@@ -564,7 +564,7 @@ export default {
},
canChangeHideDownload() {
- const hasDisabledDownload = (shareAttribute) => shareAttribute.scope === 'permissions' && shareAttribute.key === 'download'&& shareAttribute.value === false
+ const hasDisabledDownload = (shareAttribute) => shareAttribute.scope === 'permissions' && shareAttribute.key === 'download' && shareAttribute.value === false
return this.fileInfo.shareAttributes.some(hasDisabledDownload)
},
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index d9054bc7fc6..05e7f6f0282 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -35,7 +35,6 @@ import debounce from 'debounce'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
import Config from '../services/ConfigService.ts'
-import GeneratePassword from '../utils/GeneratePassword.ts'
import Share from '../models/Share.js'
import ShareRequests from '../mixins/ShareRequests.js'
import ShareTypes from '../mixins/ShareTypes.js'
diff --git a/apps/files_sharing/src/models/Share.js b/apps/files_sharing/src/models/Share.js
index dc0f8da082e..0efde5389ae 100644
--- a/apps/files_sharing/src/models/Share.js
+++ b/apps/files_sharing/src/models/Share.js
@@ -552,7 +552,6 @@ export default class Share {
return this.attributes.some(isFileRequest)
}
-
set hasDownloadPermission(enabled) {
this.setAttribute('permissions', 'download', !!enabled)
}
diff --git a/apps/files_sharing/src/services/ConfigService.ts b/apps/files_sharing/src/services/ConfigService.ts
index 916de5959c2..f8f7994bdab 100644
--- a/apps/files_sharing/src/services/ConfigService.ts
+++ b/apps/files_sharing/src/services/ConfigService.ts
@@ -4,7 +4,91 @@
*/
import { getCapabilities } from '@nextcloud/capabilities'
+type PasswordPolicyCapabilities = {
+ enforceNonCommonPassword: boolean
+ enforceNumericCharacters: boolean
+ enforceSpecialCharacters: boolean
+ enforceUpperLowerCase: boolean
+ minLength: number
+}
+
+type FileSharingCapabilities = {
+ api_enabled: boolean,
+ public: {
+ enabled: boolean,
+ password: {
+ enforced: boolean,
+ askForOptionalPassword: boolean
+ },
+ expire_date: {
+ enabled: boolean,
+ days: number,
+ enforced: boolean
+ },
+ multiple_links: boolean,
+ expire_date_internal: {
+ enabled: boolean
+ },
+ expire_date_remote: {
+ enabled: boolean
+ },
+ send_mail: boolean,
+ upload: boolean,
+ upload_files_drop: boolean
+ },
+ resharing: boolean,
+ user: {
+ send_mail: boolean,
+ expire_date: {
+ enabled: boolean
+ }
+ },
+ group_sharing: boolean,
+ group: {
+ enabled: boolean,
+ expire_date: {
+ enabled: true
+ }
+ },
+ default_permissions: number,
+ federation: {
+ outgoing: boolean,
+ incoming: boolean,
+ expire_date: {
+ enabled: boolean
+ },
+ expire_date_supported: {
+ enabled: boolean
+ }
+ },
+ sharee: {
+ query_lookup_default: boolean,
+ always_show_unique: boolean
+ },
+ sharebymail: {
+ enabled: boolean,
+ send_password_by_mail: boolean,
+ upload_files_drop: {
+ enabled: boolean
+ },
+ password: {
+ enabled: boolean,
+ enforced: boolean
+ },
+ expire_date: {
+ enabled: boolean,
+ enforced: boolean
+ }
+ }
+}
+
+type Capabilities = {
+ files_sharing: FileSharingCapabilities
+ password_policy: PasswordPolicyCapabilities
+}
+
export default class Config {
+
_capabilities: Capabilities
constructor() {
@@ -208,86 +292,3 @@ export default class Config {
}
}
-
-type PasswordPolicyCapabilities = {
- enforceNonCommonPassword: boolean
- enforceNumericCharacters: boolean
- enforceSpecialCharacters: boolean
- enforceUpperLowerCase: boolean
- minLength: number
-}
-
-type FileSharingCapabilities = {
- api_enabled: boolean,
- public: {
- enabled: boolean,
- password: {
- enforced: boolean,
- askForOptionalPassword: boolean
- },
- expire_date: {
- enabled: boolean,
- days: number,
- enforced: boolean
- },
- multiple_links: boolean,
- expire_date_internal: {
- enabled: boolean
- },
- expire_date_remote: {
- enabled: boolean
- },
- send_mail: boolean,
- upload: boolean,
- upload_files_drop: boolean
- },
- resharing: boolean,
- user: {
- send_mail: boolean,
- expire_date: {
- enabled: boolean
- }
- },
- group_sharing: boolean,
- group: {
- enabled: boolean,
- expire_date: {
- enabled: true
- }
- },
- default_permissions: number,
- federation: {
- outgoing: boolean,
- incoming: boolean,
- expire_date: {
- enabled: boolean
- },
- expire_date_supported: {
- enabled: boolean
- }
- },
- sharee: {
- query_lookup_default: boolean,
- always_show_unique: boolean
- },
- sharebymail: {
- enabled: boolean,
- send_password_by_mail: boolean,
- upload_files_drop: {
- enabled: boolean
- },
- password: {
- enabled: boolean,
- enforced: boolean
- },
- expire_date: {
- enabled: boolean,
- enforced: boolean
- }
- }
-}
-
-type Capabilities = {
- files_sharing: FileSharingCapabilities
- password_policy: PasswordPolicyCapabilities
-}
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index 2fc5219931a..cb5fbd145e9 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -19,6 +19,8 @@ use OCP\IDateTimeZone;
use OCP\IL10N;
use OCP\IPreview;
use OCP\IRequest;
+use OCP\Mail\IMailer;
+use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
use Psr\Container\ContainerInterface;
@@ -97,6 +99,8 @@ class ApiTest extends TestCase {
$previewManager = $this->createMock(IPreview::class);
$dateTimeZone = $this->createMock(IDateTimeZone::class);
$logger = $this->createMock(LoggerInterface::class);
+ $providerFactory = $this->createMock(IProviderFactory::class);
+ $mailer = $this->createMock(IMailer::class);
$dateTimeZone->method('getTimeZone')->willReturn(new \DateTimeZone(date_default_timezone_get()));
return new ShareAPIController(
@@ -115,6 +119,8 @@ class ApiTest extends TestCase {
$previewManager,
$dateTimeZone,
$logger,
+ $providerFactory,
+ $mailer,
$userId,
);
}
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index c8b8c0e94fc..c47bb6d4395 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -28,9 +28,11 @@ use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Lock\LockedException;
+use OCP\Mail\IMailer;
use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\IAttributes as IShareAttributes;
use OCP\Share\IManager;
+use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
use Psr\Container\ContainerInterface;
@@ -62,6 +64,8 @@ class ShareAPIControllerTest extends TestCase {
private IPreview|\PHPUnit\Framework\MockObject\MockObject $previewManager;
private IDateTimeZone|\PHPUnit\Framework\MockObject\MockObject $dateTimeZone;
private LoggerInterface $logger;
+ private IProviderFactory|\PHPUnit\Framework\MockObject\MockObject $factory;
+ private IMailer|\PHPUnit\Framework\MockObject\MockObject $mailer;
protected function setUp(): void {
$this->shareManager = $this->createMock(IManager::class);
@@ -95,6 +99,8 @@ class ShareAPIControllerTest extends TestCase {
});
$this->dateTimeZone = $this->createMock(IDateTimeZone::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->factory = $this->createMock(IProviderFactory::class);
+ $this->mailer = $this->createMock(IMailer::class);
$this->ocs = new ShareAPIController(
$this->appName,
@@ -112,6 +118,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
);
}
@@ -137,6 +145,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -152,7 +162,7 @@ class ShareAPIControllerTest extends TestCase {
[
'scope' => 'permissions',
'key' => 'download',
- 'enabled' => true
+ 'value' => true
]
];
@@ -360,7 +370,7 @@ class ShareAPIControllerTest extends TestCase {
// canDeleteShareFromSelf
$user = $this->createMock(IUser::class);
- $group = $this->getMockBuilder('OCP\IGroup')->getMock();
+ $group = $this->getMockBuilder(IGroup::class)->getMock();
$this->groupManager
->method('get')
->with('group')
@@ -377,7 +387,7 @@ class ShareAPIControllerTest extends TestCase {
->method('lock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);
@@ -423,7 +433,7 @@ class ShareAPIControllerTest extends TestCase {
// canDeleteShareFromSelf
$user = $this->createMock(IUser::class);
- $group = $this->getMockBuilder('OCP\IGroup')->getMock();
+ $group = $this->getMockBuilder(IGroup::class)->getMock();
$this->groupManager
->method('get')
->with('group')
@@ -440,7 +450,7 @@ class ShareAPIControllerTest extends TestCase {
->method('lock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);
@@ -522,7 +532,7 @@ class ShareAPIControllerTest extends TestCase {
$storage->method('getId')->willReturn('STORAGE');
$storage->method('getCache')->willReturn($cache);
- $parentFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $parentFolder = $this->getMockBuilder(Folder::class)->getMock();
$parentFolder->method('getId')->willReturn(3);
$file = $this->getMockBuilder('OCP\Files\File')->getMock();
@@ -534,7 +544,7 @@ class ShareAPIControllerTest extends TestCase {
$file->method('getMTime')->willReturn(1234567890);
$file->method('getMimeType')->willReturn('myMimeType');
- $folder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $folder = $this->getMockBuilder(Folder::class)->getMock();
$folder->method('getId')->willReturn(2);
$folder->method('getPath')->willReturn('folder');
$folder->method('getStorage')->willReturn($storage);
@@ -739,6 +749,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['canAccessShare'])
@@ -754,7 +766,7 @@ class ShareAPIControllerTest extends TestCase {
->with($share->getFullId(), 'currentUser')
->willReturn($share);
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$userFolder
->method('getRelativePath')
->willReturnArgument(0);
@@ -788,7 +800,7 @@ class ShareAPIControllerTest extends TestCase {
$user->method('getDisplayName')->willReturn('userDisplay');
$user->method('getSystemEMailAddress')->willReturn('userId@example.com');
- $group = $this->getMockBuilder('OCP\IGroup')->getMock();
+ $group = $this->getMockBuilder(IGroup::class)->getMock();
$group->method('getGID')->willReturn('groupId');
$this->userManager->method('get')->willReturnMap([
@@ -822,7 +834,7 @@ class ShareAPIControllerTest extends TestCase {
->with('ocinternal:42', 'currentUser')
->willReturn($share);
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);
@@ -1371,6 +1383,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -1385,7 +1399,7 @@ class ShareAPIControllerTest extends TestCase {
}
);
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$userFolder->method('get')
->with('path')
->willReturn($getSharesParameters['path']);
@@ -1447,7 +1461,7 @@ class ShareAPIControllerTest extends TestCase {
$file = $this->getMockBuilder(File::class)->getMock();
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);
@@ -1480,9 +1494,9 @@ class ShareAPIControllerTest extends TestCase {
->with($this->currentUser)
->willReturn($user);
- $group = $this->getMockBuilder('OCP\IGroup')->getMock();
+ $group = $this->getMockBuilder(IGroup::class)->getMock();
$group->method('inGroup')->with($user)->willReturn(true);
- $group2 = $this->getMockBuilder('OCP\IGroup')->getMock();
+ $group2 = $this->getMockBuilder(IGroup::class)->getMock();
$group2->method('inGroup')->with($user)->willReturn(false);
$this->groupManager->method('get')->willReturnMap([
@@ -1543,7 +1557,7 @@ class ShareAPIControllerTest extends TestCase {
* @param bool canAccessShareByHelper
*/
public function testCanAccessRoomShare(bool $expected, \OCP\Share\IShare $share, bool $helperAvailable, bool $canAccessShareByHelper) {
- $userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);
@@ -1712,6 +1726,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -1808,6 +1824,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -2228,6 +2246,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -2296,6 +2316,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -2537,6 +2559,8 @@ class ShareAPIControllerTest extends TestCase {
$this->previewManager,
$this->dateTimeZone,
$this->logger,
+ $this->factory,
+ $this->mailer,
$this->currentUser,
])->setMethods(['formatShare'])
->getMock();
@@ -3806,7 +3830,7 @@ class ShareAPIControllerTest extends TestCase {
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
- 'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]',
+ 'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
], $share, [], false
];
// User backend up
@@ -3845,7 +3869,7 @@ class ShareAPIControllerTest extends TestCase {
'can_delete' => false,
'item_size' => 123456,
'item_mtime' => 1234567890,
- 'attributes' => '[{"scope":"permissions","key":"download","enabled":true}]',
+ 'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
], $share, [
['owner', $owner],
['initiator', $initiator],
diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php
index dc796437316..f565d2e3656 100644
--- a/apps/files_sharing/tests/MountProviderTest.php
+++ b/apps/files_sharing/tests/MountProviderTest.php
@@ -70,7 +70,7 @@ class MountProviderTest extends \Test\TestCase {
$result = null;
foreach ($attrs as $attr) {
if ($attr['key'] === $key && $attr['scope'] === $scope) {
- $result = $attr['enabled'];
+ $result = $attr['value'];
}
}
return $result;
@@ -117,7 +117,7 @@ class MountProviderTest extends \Test\TestCase {
$rootFolder = $this->createMock(IRootFolder::class);
$userManager = $this->createMock(IUserManager::class);
$attr1 = [];
- $attr2 = [['scope' => 'permission', 'key' => 'download', 'enabled' => true]];
+ $attr2 = [['scope' => 'permission', 'key' => 'download', 'value' => true]];
$userShares = [
$this->makeMockShare(1, 100, 'user2', '/share2', 0, $attr1),
$this->makeMockShare(2, 100, 'user2', '/share2', 31, $attr2),
@@ -221,14 +221,14 @@ class MountProviderTest extends \Test\TestCase {
// #1: share as outsider with "group1" and "user1" with different permissions
[
[
- [1, 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'enabled' => true], ['scope' => 'app', 'key' => 'attribute1', 'enabled' => true]]],
+ [1, 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true]]],
],
[
- [2, 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'enabled' => false], ['scope' => 'app', 'key' => 'attribute2', 'enabled' => false]]],
+ [2, 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
],
[
// use highest permissions
- ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'enabled' => true], ['scope' => 'app', 'key' => 'attribute1', 'enabled' => true], ['scope' => 'app', 'key' => 'attribute2', 'enabled' => false]]],
+ ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
],
],
// #2: share as outsider with "group1" and "group2" with same permissions
@@ -249,12 +249,12 @@ class MountProviderTest extends \Test\TestCase {
[
],
[
- [1, 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'enabled' => false]]],
- [2, 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'enabled' => true]]],
+ [1, 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
+ [2, 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
],
[
// use higher permissions (most permissive)
- ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'enabled' => true]]],
+ ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
],
],
// #4: share as insider with "group1"
@@ -273,8 +273,8 @@ class MountProviderTest extends \Test\TestCase {
[
],
[
- [1, 100, 'user1', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'enabled' => true]]],
- [2, 100, 'user1', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'enabled' => false]]],
+ [1, 100, 'user1', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
+ [2, 100, 'user1', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
],
[
// no received share since "user1" is the sharer/owner
diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php
index b2a7233548f..ab9433f51c8 100644
--- a/apps/sharebymail/lib/ShareByMailProvider.php
+++ b/apps/sharebymail/lib/ShareByMailProvider.php
@@ -106,7 +106,11 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
$data = $this->getRawShare($shareId);
// Temporary set the clear password again to send it by mail
- $data['password'] = $password;
+ // This need to be done after the share was created in the database
+ // as the password is hashed in between.
+ if (!empty($password)) {
+ $data['password'] = $password;
+ }
return $this->createShareObject($data);
}
@@ -257,8 +261,11 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
// If we have a password set, we send it to the recipient
if ($share->getPassword() !== null) {
- // Sends share password to receiver when it's a permanent one (otherwise she will have to request it via the showShare UI)
- // or to owner when the password shall be given during a Talk session
+ // If share-by-talk password is enabled, we do not send the notification
+ // to the recipient. They will have to request it to the owner after opening the link.
+ // Secondly, if the password expiration is disabled, we send the notification to the recipient
+ // Lastly, if the mail to recipient failed, we send the password to the owner as a fallback.
+ // If a password expires, the recipient will still be able to request a new one via talk.
$passwordExpire = $this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false);
$passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
if ($passwordExpire === false || $share->getSendPasswordByTalk()) {
@@ -283,8 +290,12 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
'exception' => $e,
]);
$this->removeShareFromTable((int)$shareId);
- throw new HintException('Failed to send share by mail',
- $this->l->t('Failed to send share by email'));
+ throw new HintException(
+ 'Failed to send share by mail',
+ $this->l->t('Failed to send share by email'),
+ 0,
+ $e,
+ );
}
return false;
}
@@ -359,10 +370,14 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
// The "Reply-To" is set to the sharer if an mail address is configured
// also the default footer contains a "Do not reply" which needs to be adjusted.
- $initiatorEmail = $initiatorUser->getEMailAddress();
- if ($this->settingsManager->replyToInitiator() && $initiatorEmail !== null) {
- $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
- $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
+ if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
+ $initiatorEmail = $initiatorUser->getEMailAddress();
+ if ($initiatorEmail !== null) {
+ $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
+ $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
+ } else {
+ $emailTemplate->addFooter();
+ }
} else {
$emailTemplate->addFooter();
}
@@ -451,10 +466,14 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
// The "Reply-To" is set to the sharer if an mail address is configured
// also the default footer contains a "Do not reply" which needs to be adjusted.
- $initiatorEmail = $initiatorUser->getEMailAddress();
- if ($this->settingsManager->replyToInitiator() && $initiatorEmail !== null) {
- $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
- $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
+ if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
+ $initiatorEmail = $initiatorUser->getEMailAddress();
+ if ($initiatorEmail !== null) {
+ $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
+ $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
+ } else {
+ $emailTemplate->addFooter();
+ }
} else {
$emailTemplate->addFooter();
}
@@ -714,7 +733,7 @@ class ShareByMailProvider extends DefaultShareProvider implements IShareProvider
->set('note', $qb->createNamedParameter($share->getNote()))
->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
->set('attributes', $qb->createNamedParameter($shareAttributes))
- ->set('mail_send', $qb->createNamedParameter($share->getMailSend(), IQueryBuilder::PARAM_INT))
+ ->set('mail_send', $qb->createNamedParameter((int)$share->getMailSend(), IQueryBuilder::PARAM_INT))
->executeStatement();
if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
diff --git a/apps/sharebymail/tests/ShareByMailProviderTest.php b/apps/sharebymail/tests/ShareByMailProviderTest.php
index 71af50e1a1b..c7f41176c44 100644
--- a/apps/sharebymail/tests/ShareByMailProviderTest.php
+++ b/apps/sharebymail/tests/ShareByMailProviderTest.php
@@ -24,6 +24,7 @@ use OCP\Mail\IMessage;
use OCP\Security\Events\GenerateSecurePasswordEvent;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
+use OCP\Share\IAttributes;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
@@ -110,6 +111,7 @@ class ShareByMailProviderTest extends TestCase {
$this->shareManager = $this->getMockBuilder(IManager::class)->getMock();
$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
+ $this->config->expects($this->any())->method('getAppValue')->with('core', 'enforce_strict_email_check')->willReturn('yes');
}
/**
@@ -119,9 +121,9 @@ class ShareByMailProviderTest extends TestCase {
* @return \PHPUnit\Framework\MockObject\MockObject | ShareByMailProvider
*/
private function getInstance(array $mockedMethods = []) {
- $instance = $this->getMockBuilder('OCA\ShareByMail\ShareByMailProvider')
- ->setConstructorArgs(
- [
+ if (!empty($mockedMethods)) {
+ return $this->getMockBuilder('OCA\ShareByMail\ShareByMailProvider')
+ ->setConstructorArgs([
$this->config,
$this->connection,
$this->secureRandom,
@@ -137,12 +139,9 @@ class ShareByMailProviderTest extends TestCase {
$this->hasher,
$this->eventDispatcher,
$this->shareManager
- ]
- );
-
- if (!empty($mockedMethods)) {
- $instance->setMethods($mockedMethods);
- return $instance->getMock();
+ ])
+ ->setMethods($mockedMethods)
+ ->getMock();
}
return new ShareByMailProvider(
@@ -179,17 +178,22 @@ class ShareByMailProviderTest extends TestCase {
$node = $this->getMockBuilder(File::class)->getMock();
$node->expects($this->any())->method('getName')->willReturn('filename');
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'sendPassword']);
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'sendEmail', 'sendPassword']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
$instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
$instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
- $instance->expects($this->any())->method('sendPassword')->willReturn(true);
$share->expects($this->any())->method('getNode')->willReturn($node);
- $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
- $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
+
+ // As share api link password is not enforced, the password will not be generated.
+ $this->shareManager->expects($this->once())->method('shareApiLinkEnforcePassword')->willReturn(false);
+ $this->settingsManager->expects($this->never())->method('sendPasswordByMail');
+
+ // Mail notification is triggered by the share manager.
+ $instance->expects($this->never())->method('sendEmail');
+ $instance->expects($this->never())->method('sendPassword');
$this->assertSame($expectedShare, $instance->create($share));
}
@@ -197,16 +201,22 @@ class ShareByMailProviderTest extends TestCase {
public function testCreateSendPasswordByMailWithoutEnforcedPasswordProtection() {
$expectedShare = $this->createMock(IShare::class);
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@examplelölöl.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
-
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
@@ -219,32 +229,45 @@ class ShareByMailProviderTest extends TestCase {
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
$instance->expects($this->never())->method('autoGeneratePassword');
- $this->mailer->expects($this->never())->method('send');
+ // No password is set and no password sent via talk is requested
+ $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@examplelölöl.com']);
+ $instance->expects($this->never())->method('sendPassword');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
+ // The manager sends the mail notification.
+ // For the sake of testing simplicity, we will handle it ourselves.
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword() {
$expectedShare = $this->createMock(IShare::class);
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
- $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
- $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
$share->expects($this->any())->method('getNode')->willReturn($node);
- $share->expects($this->once())->method('getPassword')->willReturn('password');
+ $share->expects($this->any())->method('getPassword')->willReturn('password');
$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
$share->expects($this->once())->method('setPassword')->with('passwordHashed');
@@ -254,60 +277,82 @@ class ShareByMailProviderTest extends TestCase {
$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
$instance->expects($this->never())->method('autoGeneratePassword');
+ // A password is set but no password sent via talk has been requested
+ $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@example.com']);
+ $instance->expects($this->once())->method('sendPassword')->with($share, 'password');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
+
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithoutPermanentPassword() {
$expectedShare = $this->createMock(IShare::class);
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
- $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
- $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
$share->expects($this->any())->method('getNode')->willReturn($node);
- $share->expects($this->once())->method('getPassword')->willReturn('password');
+ $share->expects($this->any())->method('getPassword')->willReturn('password');
$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
$share->expects($this->once())->method('setPassword')->with('passwordHashed');
- // The given password (but not the autogenerated password) should be
- // mailed to the receiver of the share because permanent passwords are enforced.
+ // No password is generated, so no emails need to be sent
+ // aside from the main email notification.
$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
$instance->expects($this->never())->method('autoGeneratePassword');
- $this->config->expects($this->any())->method('getSystemValue')->withConsecutive(
- ['sharing.enable_mail_link_password_expiration'],
- ['sharing.enable_mail_link_password_expiration'],
- ['sharing.mail_link_password_expiration_interval']
- )->willReturnOnConsecutiveCalls(
- true,
- true,
- 3600
- );
+ $this->config->expects($this->once())->method('getSystemValue')
+ ->with('sharing.enable_mail_link_password_expiration')
+ ->willReturn(true);
+
+ // No password has been set and no password sent via talk has been requested,
+ // but password has been enforced for the whole instance and will be generated.
+ $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@example.com']);
+ $instance->expects($this->never())->method('sendPassword');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
public function testCreateSendPasswordByMailWithEnforcedPasswordProtectionWithPermanentPassword() {
$expectedShare = $this->createMock(IShare::class);
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
$this->secureRandom->expects($this->once())
->method('generate')
@@ -317,16 +362,19 @@ class ShareByMailProviderTest extends TestCase {
->method('dispatchTyped')
->with(new GenerateSecurePasswordEvent());
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'createPasswordSendActivity']);
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
+
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'createPasswordSendActivity', 'sendPasswordToOwner']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
- $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
- $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
- $share->expects($this->any())->method('getNode')->willReturn($node);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
- $share->expects($this->once())->method('getPassword')->willReturn(null);
+ // Initially not set, but will be set by the autoGeneratePassword method.
+ $share->expects($this->exactly(3))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword');
$this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
$share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
@@ -336,41 +384,69 @@ class ShareByMailProviderTest extends TestCase {
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
$message = $this->createMock(IMessage::class);
- $message->expects($this->once())->method('setTo')->with(['receiver@example.com']);
- $this->mailer->expects($this->once())->method('createMessage')->willReturn($message);
- $this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.RecipientPasswordNotification', [
- 'filename' => 'filename',
- 'password' => 'autogeneratedPassword',
- 'initiator' => 'owner',
- 'initiatorEmail' => null,
- 'shareWith' => 'receiver@example.com',
- ]);
- $this->mailer->expects($this->once())->method('send');
+ $message->expects($this->exactly(2))->method('setTo')->with(['receiver@example.com']);
+ $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
+ $this->mailer->expects($this->exactly(2))->method('createEMailTemplate')
+ ->withConsecutive([
+ 'sharebymail.RecipientNotification', [
+ 'filename' => 'filename',
+ 'link' => 'https://example.com/file.txt',
+ 'initiator' => 'owner',
+ 'expiration' => null,
+ 'shareWith' => 'receiver@example.com',
+ 'note' => ''
+ ]
+ ],
+ [
+ 'sharebymail.RecipientPasswordNotification', [
+ 'filename' => 'filename',
+ 'password' => 'autogeneratedPassword',
+ 'initiator' => 'owner',
+ 'initiatorEmail' => null,
+ 'shareWith' => 'receiver@example.com',
+ ]
+ ]);
+
+ // Main email notification is sent as well as the password
+ // to the recipient because shareApiLinkEnforcePassword is enabled.
+ $this->mailer->expects($this->exactly(2))->method('send');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
public function testCreateSendPasswordByMailWithPasswordAndWithEnforcedPasswordProtectionWithPermanentPassword() {
$expectedShare = $this->createMock(IShare::class);
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
- $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
+
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendPasswordToOwner']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
- $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
- $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
- $share->expects($this->any())->method('getNode')->willReturn($node);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
- $share->expects($this->once())->method('getPassword')->willReturn('password');
+ $share->expects($this->exactly(3))->method('getPassword')->willReturn('password');
$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
$share->expects($this->once())->method('setPassword')->with('passwordHashed');
@@ -382,41 +458,75 @@ class ShareByMailProviderTest extends TestCase {
$instance->expects($this->never())->method('autoGeneratePassword');
$message = $this->createMock(IMessage::class);
- $message->expects($this->once())->method('setTo')->with(['receiver@example.com']);
- $this->mailer->expects($this->once())->method('createMessage')->willReturn($message);
- $this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.RecipientPasswordNotification', [
- 'filename' => 'filename',
- 'password' => 'password',
- 'initiator' => 'owner',
- 'initiatorEmail' => null,
- 'shareWith' => 'receiver@example.com',
- ]);
- $this->mailer->expects($this->once())->method('send');
+ $message->expects($this->exactly(2))->method('setTo')->with(['receiver@example.com']);
+ $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
+ $this->mailer->expects($this->exactly(2))->method('createEMailTemplate')
+ ->withConsecutive([
+ 'sharebymail.RecipientNotification', [
+ 'filename' => 'filename',
+ 'link' => 'https://example.com/file.txt',
+ 'initiator' => 'owner',
+ 'expiration' => null,
+ 'shareWith' => 'receiver@example.com',
+ 'note' => ''
+ ]
+ ],
+ [
+ 'sharebymail.RecipientPasswordNotification', [
+ 'filename' => 'filename',
+ 'password' => 'password',
+ 'initiator' => 'owner',
+ 'initiatorEmail' => null,
+ 'shareWith' => 'receiver@example.com',
+ ]
+ ]);
+
+ // Main email notification is sent as well as the password
+ // to the recipient because the password is set.
+ $this->mailer->expects($this->exactly(2))->method('send');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
public function testCreateSendPasswordByTalkWithEnforcedPasswordProtectionWithPermanentPassword() {
$expectedShare = $this->createMock(IShare::class);
+ // The owner of the share.
+ $owner = $this->getMockBuilder(IUser::class)->getMock();
+ $this->userManager->expects($this->any())->method('get')->with('owner')->willReturn($owner);
+ $owner->expects($this->any())->method('getEMailAddress')->willReturn('owner@example.com');
+ $owner->expects($this->any())->method('getDisplayName')->willReturn('owner');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(true);
$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
- $node = $this->getMockBuilder(File::class)->getMock();
- $node->expects($this->any())->method('getName')->willReturn('filename');
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
$instance->expects($this->once())->method('createShareActivity')->with($share);
- $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare']);
- $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
- $share->expects($this->any())->method('getNode')->willReturn($node);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
- $share->expects($this->once())->method('getPassword')->willReturn(null);
+ $share->expects($this->exactly(4))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword', 'autogeneratedPassword');
$this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
$share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
@@ -427,26 +537,103 @@ class ShareByMailProviderTest extends TestCase {
$instance->expects($this->once())->method('autoGeneratePassword')->with($share)->willReturn('autogeneratedPassword');
$message = $this->createMock(IMessage::class);
- $message->expects($this->once())->method('setTo')->with(['owner@example.com' => 'Owner display name']);
- $this->mailer->expects($this->once())->method('createMessage')->willReturn($message);
- $this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.OwnerPasswordNotification', [
- 'filename' => 'filename',
- 'password' => 'autogeneratedPassword',
- 'initiator' => 'Owner display name',
- 'initiatorEmail' => 'owner@example.com',
- 'shareWith' => 'receiver@example.com',
+ $message->expects($this->exactly(2))->method('setTo')->withConsecutive([['receiver@example.com']], [['owner@example.com' => 'owner']]);
+ $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
+ $this->mailer->expects($this->exactly(2))->method('createEMailTemplate')
+ ->withConsecutive([
+ 'sharebymail.RecipientNotification', [
+ 'filename' => 'filename',
+ 'link' => 'https://example.com/file.txt',
+ 'initiator' => 'owner',
+ 'expiration' => null,
+ 'shareWith' => 'receiver@example.com',
+ 'note' => ''
+ ]
+ ],
+ [
+ 'sharebymail.OwnerPasswordNotification', [
+ 'filename' => 'filename',
+ 'password' => 'autogeneratedPassword',
+ 'initiator' => 'owner',
+ 'initiatorEmail' => 'owner@example.com',
+ 'shareWith' => 'receiver@example.com',
+ ]
+ ]);
+
+ // Main email notification is sent as well as the password to owner
+ // because the password is set and SendPasswordByTalk is enabled.
+ $this->mailer->expects($this->exactly(2))->method('send');
+
+ $this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
+ }
+
+ // If attributes is set to multiple emails, use them as BCC
+ public function sendNotificationToMultipleEmails() {
+ $expectedShare = $this->createMock(IShare::class);
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('filename');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedWith')->willReturn('');
+ $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
+ $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
+ $attributes = $this->getMockBuilder(IAttributes::class)->getMock();
+ $share->expects($this->any())->method('getAttributes')->willReturn($attributes);
+ $attributes->expects($this->any())->method('getAttribute')->with('shareWith', 'emails')->willReturn([
+ 'receiver1@example.com',
+ 'receiver2@example.com',
+ 'receiver3@example.com',
]);
- $this->mailer->expects($this->once())->method('send');
- $user = $this->createMock(IUser::class);
- $this->userManager->expects($this->once())->method('get')->with('owner')->willReturn($user);
- $user->expects($this->once())->method('getDisplayName')->willReturn('Owner display name');
- $user->expects($this->once())->method('getEMailAddress')->willReturn('owner@example.com');
+ // Assume the mail address is valid.
+ $this->mailer->expects($this->any())->method('validateMailAddress')->willReturn(true);
+
+ $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
+
+ $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
+ $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn(42);
+ $instance->expects($this->once())->method('createShareActivity')->with($share);
+ $instance->expects($this->once())->method('getRawShare')->with(42)->willReturn(['rawShare', 'password' => 'password']);
+ $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+
+ $share->expects($this->any())->method('getPassword')->willReturn('password');
+ $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
+ $share->expects($this->once())->method('setPassword')->with('passwordHashed');
+
+ // The given password (but not the autogenerated password) should not be
+ // mailed to the receiver of the share because permanent passwords are not enforced.
+ $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
+ $this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
+ $instance->expects($this->never())->method('autoGeneratePassword');
+
+ // A password is set but no password sent via talk has been requested
+ $instance->expects($this->once())->method('sendEmail')
+ ->with($share, ['receiver1@example.com', 'receiver2@example.com', 'receiver3@example.com']);
+ $instance->expects($this->once())->method('sendPassword')->with($share, 'password');
+ $instance->expects($this->never())->method('sendPasswordToOwner');
+
+
+ $message = $this->createMock(IMessage::class);
+ $message->expects($this->never())->method('setTo');
+ $message->expects($this->exactly(2))->method('setBcc')->with(['receiver1@example.com', 'receiver2@example.com', 'receiver3@example.com']);
+ $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
+
+ // Main email notification is sent as well as the password
+ // to recipients because the password is set.
+ $this->mailer->expects($this->exactly(2))->method('send');
$this->assertSame($expectedShare, $instance->create($share));
+ $instance->sendMailNotification($share);
}
-
public function testCreateFailed() {
$this->expectException(\Exception::class);
@@ -473,33 +660,8 @@ class ShareByMailProviderTest extends TestCase {
$this->share->expects($this->any())->method('getSharedBy')->willReturn('validby@valid.com');
$this->share->expects($this->any())->method('getSharedWith')->willReturn('validwith@valid.com');
$this->share->expects($this->any())->method('getNote')->willReturn('Check this!');
- $node = $this->getMockBuilder('OCP\Files\Node')->getMock();
- $node->expects($this->any())->method('getName')->willReturn('fileName');
- $this->share->expects($this->any())->method('getNode')->willReturn($node);
+ $this->share->expects($this->any())->method('getMailSend')->willReturn(true);
- $instance = $this->getInstance(['generateToken', 'addShareToDB', 'sendMailNotification']);
-
- $instance->expects($this->once())->method('generateToken')->willReturn('token');
- $instance->expects($this->once())->method('addShareToDB')->willReturn(42);
- $instance->expects($this->once())->method('sendMailNotification');
- $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
- ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']);
- $instance->expects($this->once())->method('sendMailNotification');
-
- $this->assertSame(42,
- $this->invokePrivate($instance, 'createMailShare', [$this->share])
- );
- }
-
-
- public function testCreateMailShareFailed() {
- $this->expectException(\OCP\HintException::class);
-
- $this->share->expects($this->any())->method('getToken')->willReturn('token');
- $this->share->expects($this->once())->method('setToken')->with('token');
- $this->share->expects($this->any())->method('getSharedBy')->willReturn('validby@valid.com');
- $this->share->expects($this->any())->method('getSharedWith')->willReturn('validwith@valid.com');
- $this->share->expects($this->any())->method('getNote')->willReturn('Check this!');
$node = $this->getMockBuilder('OCP\Files\Node')->getMock();
$node->expects($this->any())->method('getName')->willReturn('fileName');
$this->share->expects($this->any())->method('getNode')->willReturn($node);
@@ -508,15 +670,9 @@ class ShareByMailProviderTest extends TestCase {
$instance->expects($this->once())->method('generateToken')->willReturn('token');
$instance->expects($this->once())->method('addShareToDB')->willReturn(42);
- $instance->expects($this->once())->method('sendMailNotification');
- $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
- ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']);
- $instance->expects($this->once())->method('sendMailNotification')
- ->willReturnCallback(
- function () {
- throw new \Exception('should be converted to a hint exception');
- }
- );
+
+ // The manager handle the mail sending
+ $instance->expects($this->never())->method('sendMailNotification');
$this->assertSame(42,
$this->invokePrivate($instance, 'createMailShare', [$this->share])
@@ -1195,22 +1351,35 @@ class ShareByMailProviderTest extends TestCase {
->expects($this->once())
->method('useTemplate')
->with($template);
+
+ $this->mailer->expects($this->once())
+ ->method('validateMailAddress')
+ ->willReturn(true);
$this->mailer
->expects($this->once())
->method('send')
->with($message);
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('file.txt');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
+ $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
self::invokePrivate(
$provider,
'sendMailNotification',
- [
- 'file.txt',
- 'https://example.com/file.txt',
- 'OwnerUser',
- 'john@doe.com',
- null,
- ''
- ]);
+ [$share]
+ );
}
public function testSendMailNotificationWithSameUserAndUserEmailAndNote() {
@@ -1295,22 +1464,35 @@ class ShareByMailProviderTest extends TestCase {
->expects($this->once())
->method('useTemplate')
->with($template);
+
+ $this->mailer->expects($this->once())
+ ->method('validateMailAddress')
+ ->willReturn(true);
$this->mailer
->expects($this->once())
->method('send')
->with($message);
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('file.txt');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
+ $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('This is a note to the recipient');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
self::invokePrivate(
$provider,
'sendMailNotification',
- [
- 'file.txt',
- 'https://example.com/file.txt',
- 'OwnerUser',
- 'john@doe.com',
- null,
- 'This is a note to the recipient'
- ]);
+ [$share]
+ );
}
public function testSendMailNotificationWithDifferentUserAndNoUserEmail() {
@@ -1386,21 +1568,35 @@ class ShareByMailProviderTest extends TestCase {
->expects($this->once())
->method('useTemplate')
->with($template);
+
+ $this->mailer->expects($this->once())
+ ->method('validateMailAddress')
+ ->willReturn(true);
$this->mailer
->expects($this->once())
->method('send')
->with($message);
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('file.txt');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
+ $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
self::invokePrivate(
$provider,
'sendMailNotification',
- [
- 'file.txt',
- 'https://example.com/file.txt',
- 'InitiatorUser',
- 'john@doe.com',
- null,
- ]);
+ [$share]
+ );
}
public function testSendMailNotificationWithSameUserAndUserEmailAndReplyToDesactivate() {
@@ -1461,10 +1657,10 @@ class ShareByMailProviderTest extends TestCase {
->with([
\OCP\Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud'
]);
+ // Since replyToInitiator is false, we never get the initiator email address
$user
- ->expects($this->once())
- ->method('getEMailAddress')
- ->willReturn('owner@example.com');
+ ->expects($this->never())
+ ->method('getEMailAddress');
$message
->expects($this->never())
->method('setReplyTo');
@@ -1480,21 +1676,35 @@ class ShareByMailProviderTest extends TestCase {
->expects($this->once())
->method('useTemplate')
->with($template);
+
+ $this->mailer->expects($this->once())
+ ->method('validateMailAddress')
+ ->willReturn(true);
$this->mailer
->expects($this->once())
->method('send')
->with($message);
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('file.txt');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
+ $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
self::invokePrivate(
$provider,
'sendMailNotification',
- [
- 'file.txt',
- 'https://example.com/file.txt',
- 'OwnerUser',
- 'john@doe.com',
- null,
- ]);
+ [$share]
+ );
}
public function testSendMailNotificationWithDifferentUserAndNoUserEmailAndReplyToDesactivate() {
@@ -1570,20 +1780,34 @@ class ShareByMailProviderTest extends TestCase {
->expects($this->once())
->method('useTemplate')
->with($template);
+
+ $this->mailer->expects($this->once())
+ ->method('validateMailAddress')
+ ->willReturn(true);
$this->mailer
->expects($this->once())
->method('send')
->with($message);
+ $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
+ ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
+ ->willReturn('https://example.com/file.txt');
+
+ $node = $this->getMockBuilder(File::class)->getMock();
+ $node->expects($this->any())->method('getName')->willReturn('file.txt');
+
+ $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
+ $share->expects($this->any())->method('getSharedWith')->willReturn('john@doe.com');
+ $share->expects($this->any())->method('getNode')->willReturn($node);
+ $share->expects($this->any())->method('getId')->willReturn(42);
+ $share->expects($this->any())->method('getNote')->willReturn('');
+ $share->expects($this->any())->method('getToken')->willReturn('token');
+
self::invokePrivate(
$provider,
'sendMailNotification',
- [
- 'file.txt',
- 'https://example.com/file.txt',
- 'InitiatorUser',
- 'john@doe.com',
- null,
- ]);
+ [$share]
+ );
}
}