Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show sharee in dropdown to send notification mail again #6276

Closed
5 changes: 5 additions & 0 deletions apps/files_sharing/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
'url' => '/api/v1/shares',
'verb' => 'POST',
],
[
'name' => 'ShareAPI#resendMailNotification',
'url' => '/api/v1/shares/{id}/resendMailNotification',
'verb' => 'POST',
],
[
'name' => 'ShareAPI#getShare',
'url' => '/api/v1/shares/{id}',
Expand Down
25 changes: 25 additions & 0 deletions apps/files_sharing/lib/Controller/ShareAPIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,31 @@ public function createShare(
return new DataResponse($output);
}

/**
* Sends again the e-mail notification for a share
*
* @NoAdminRequired
*
* @param string $id
* @return DataResponse
* @throws OCSNotFoundException
*/
public function resendMailNotification($id) {
try {
$share = $this->getShareById($id);
} catch (ShareNotFound $e) {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist', $id));
}

if (!$this->canAccessShare($share)) {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist', $id));
}

$this->shareManager->resendMailNotification($share);

return new DataResponse();
}

/**
* @param \OCP\Files\File|\OCP\Files\Folder $node
* @param boolean $includeTags
Expand Down
112 changes: 112 additions & 0 deletions apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,118 @@ public function testCreateReshareOfFederatedMountNoDeletePermissions() {
$ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_USER, 'validUser');
}

public function testResendMailNotification() {
$share = $this->createShare(42, \OCP\Share::SHARE_TYPE_USER, null, null, null, null, null, null, null, null, null, null);

/** @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,
])->setMethods(['canAccessShare'])
->getMock();

$this->shareManager
->expects($this->once())
->method('getShareById')
->with('ocinternal:42')
->willReturn($share);

$ocs->expects($this->once())
->method('canAccessShare')
->with($share)
->willReturn(true);

$this->shareManager
->expects($this->once())
->method('resendMailNotification')
->with($share);

$ocs->resendMailNotification(42);
}

/**
* @expectedException \OCP\AppFramework\OCS\OCSNotFoundException
* @expectedExceptionMessage Wrong share ID, share doesn't exist
*/
public function testResendMailNotificationShareNotFound() {
$share = $this->createShare(42, \OCP\Share::SHARE_TYPE_USER, null, null, null, null, null, null, null, null, null, null);

/** @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,
])->setMethods(['canAccessShare'])
->getMock();

$this->shareManager
->expects($this->once())
->method('getShareById')
->with('ocinternal:42')
->will($this->throwException(new \OCP\Share\Exceptions\ShareNotFound()));

$this->shareManager
->expects($this->never())
->method('resendMailNotification');

$ocs->resendMailNotification(42);
}

/**
* @expectedException \OCP\AppFramework\OCS\OCSNotFoundException
* @expectedExceptionMessage Wrong share ID, share doesn't exist
*/
public function testResendMailNotificationCanNotAccess() {
$share = $this->createShare(42, \OCP\Share::SHARE_TYPE_USER, null, null, null, null, null, null, null, null, null, null);

/** @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,
])->setMethods(['canAccessShare'])
->getMock();

$this->shareManager
->expects($this->once())
->method('getShareById')
->with('ocinternal:42')
->willReturn($share);

$ocs->expects($this->once())
->method('canAccessShare')
->with($share)
->willReturn(false);

$this->shareManager
->expects($this->never())
->method('resendMailNotification');

$ocs->resendMailNotification(42);
}

/**
* @expectedException \OCP\AppFramework\OCS\OCSNotFoundException
* @expectedExceptionMessage Wrong share ID, share doesn't exist
Expand Down
9 changes: 9 additions & 0 deletions core/css/share.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@

.share-autocomplete-item {
display: flex;
position: relative; // A relative position is needed here to place the mail
// icon to the right of the item and, like the text, to
// also get its position modified by the invisible
// border added when the item is focused.
.autocomplete-item-text {
margin-left: 10px;
margin-right: 10px;
Expand All @@ -79,6 +83,11 @@
line-height: 32px;
vertical-align: middle;
}
.icon-mail {
position: absolute;
top: 8px;
right: 8px;
}
}

.ui-autocomplete .autocomplete-note {
Expand Down
40 changes: 34 additions & 6 deletions core/js/sharedialogview.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,11 @@
usersLength = users.length;
for (j = 0; j < usersLength; j++) {
if (users[j].value.shareWith === share.share_with) {
users.splice(j, 1);
if (users[j].value.hasEmailAddress === true) {
users[j].resendMailNotification = share.id;
} else {
users.splice(j, 1);
}
break;
}
}
Expand All @@ -262,7 +266,7 @@
emailsLength = emails.length;
for (j = 0; j < emailsLength; j++) {
if (emails[j].value.shareWith === share.share_with) {
emails.splice(j, 1);
remotes.splice(j, 1);
break;
}
}
Expand Down Expand Up @@ -347,7 +351,14 @@
$("<div class='autocomplete-item-text'></div>")
.text(text)
.appendTo(insert);
insert.attr('title', item.value.shareWith);

if (item.resendMailNotification !== undefined) {
$("<span class='icon-mail'></div>").appendTo(insert);
insert.attr('title', t('core', 'Send e-mail notification again to {sharee}', {sharee: item.value.shareWith}));
} else {
insert.attr('title', item.value.shareWith);
}

insert = $("<a>")
.append(insert);
return $("<li>")
Expand All @@ -366,20 +377,37 @@
var $shareInfo = this.$el.find('.shareWithRemoteInfo');
$shareInfo.addClass('hidden');

this.model.addShare(s.item.value, {success: function() {
var actionSuccess = function() {
$(e.target).val('')
.attr('disabled', false);
$loading.addClass('hidden')
.removeClass('inlineblock');
$shareInfo.removeClass('hidden');
}, error: function(obj, msg) {
};

var actionError = function(obj, msg) {
OC.Notification.showTemporary(msg);
$(e.target).attr('disabled', false)
.autocomplete('search', $(e.target).val());
$loading.addClass('hidden')
.removeClass('inlineblock');
$shareInfo.removeClass('hidden');
}});
};

if (s.item.resendMailNotification !== undefined) {
this.model.resendMailNotification(s.item.resendMailNotification, {
success: function(msg) {
OC.Notification.showTemporary(msg);
actionSuccess();
},
error: actionError
});
} else {
this.model.addShare(s.item.value, {
success: actionSuccess,
error: actionError
});
}
},

_toggleLoading: function(state) {
Expand Down
32 changes: 32 additions & 0 deletions core/js/shareitemmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,38 @@
});
},

/**
* Sends again the e-mail notification for a share
*
* @param {int} shareId the share ID
* @param {object} options an object with optional callbacks for success
* and error
* @return {jqXHR}
*/
resendMailNotification: function(shareId, options) {
return $.ajax({
type: 'POST',
url: this._getUrl('shares/' + encodeURIComponent(shareId) + "/resendMailNotification"),
dataType: 'json'
}).done(function() {
if (_.isFunction(options.success)) {
options.success(t('core', 'E-mail notification sent again'));
}
}).fail(function(xhr) {
var msg = t('core', 'Error');
var result = xhr.responseJSON;
if (result && result.ocs && result.ocs.meta) {
msg = result.ocs.meta.message;
}

if (_.isFunction(options.error)) {
options.error(self, msg);
} else {
OC.dialogs.alert(msg, t('core', 'Error when sending again the e-mail notification'));
}
});
},

/**
* @returns {boolean}
*/
Expand Down
Loading