mirror of
https://github.com/nextcloud/server.git
synced 2026-02-28 20:40:39 -05:00
Various improvements related to the recent implementation of temporary passwords
for mail shares: 1- Changes style of "forgot password?" and "Back" button 2- Adds information about share password's expiration time in the emails sent. 3- Shows password expiration time in the Share menu 4- Fixes an issue when the message "Password expires..." would be shown for non email share types (which don't have temporary passswords) 5- At share's creation, password should only be sent when it's a permanent one See also https://github.com/nextcloud/server/issues/31952 Signed-off-by: Cyrille Bollu <cyrpub@bollu.be> Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
This commit is contained in:
parent
1cf2ed484e
commit
e35cbd2a6b
10 changed files with 89 additions and 36 deletions
|
|
@ -279,7 +279,7 @@ class ShareAPIController extends OCSController {
|
|||
} elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
|
||||
$result['share_with'] = $share->getSharedWith();
|
||||
$result['password'] = $share->getPassword();
|
||||
$result['password_expiration_time'] = $share->getPasswordExpirationTime();
|
||||
$result['password_expiration_time'] = $share->getPasswordExpirationTime() !== null ? $share->getPasswordExpirationTime()->format(\DateTime::ATOM) : null;
|
||||
$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
|
||||
$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
|
||||
$result['token'] = $share->getToken();
|
||||
|
|
|
|||
|
|
@ -192,6 +192,12 @@
|
|||
@submit="onPasswordSubmit">
|
||||
{{ t('files_sharing', 'Enter a password') }}
|
||||
</ActionInput>
|
||||
<ActionText v-if="isEmailShareType && passwordExpirationTime" icon="icon-info">
|
||||
{{ t('files_sharing', 'Password expires {passwordExpirationTime}', {passwordExpirationTime}) }}
|
||||
</ActionText>
|
||||
<ActionText v-else-if="isEmailShareType && passwordExpirationTime !== null" icon="icon-error">
|
||||
{{ t('files_sharing', 'Password expired') }}
|
||||
</ActionText>
|
||||
|
||||
<!-- password protected by Talk -->
|
||||
<ActionCheckbox v-if="isPasswordProtectedByTalkAvailable"
|
||||
|
|
@ -461,6 +467,20 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
passwordExpirationTime() {
|
||||
if (this.share.passwordExpirationTime === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const expirationTime = moment(this.share.passwordExpirationTime)
|
||||
|
||||
if (expirationTime.diff(moment()) < 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
return expirationTime.fromNow()
|
||||
},
|
||||
|
||||
/**
|
||||
* Is Talk enabled?
|
||||
*
|
||||
|
|
|
|||
|
|
@ -103,8 +103,9 @@ export default {
|
|||
const request = await axios.put(shareUrl + `/${id}`, properties)
|
||||
if (!request?.data?.ocs) {
|
||||
throw request
|
||||
} else {
|
||||
return request.data.ocs.data
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('Error while updating share', error)
|
||||
if (error.response.status !== 400) {
|
||||
|
|
|
|||
|
|
@ -235,11 +235,14 @@ export default {
|
|||
this.saving = true
|
||||
this.errors = {}
|
||||
try {
|
||||
await this.updateShare(this.share.id, properties)
|
||||
const updatedShare = await this.updateShare(this.share.id, properties)
|
||||
|
||||
if (propertyNames.indexOf('password') >= 0) {
|
||||
// reset password state after sync
|
||||
this.$delete(this.share, 'newPassword')
|
||||
|
||||
// updates password expiration time after sync
|
||||
this.share.passwordExpirationTime = updatedShare.password_expiration_time
|
||||
}
|
||||
|
||||
// clear any previous errors
|
||||
|
|
|
|||
|
|
@ -358,6 +358,27 @@ export default class Share {
|
|||
this._share.password = password
|
||||
}
|
||||
|
||||
/**
|
||||
* Password expiration time
|
||||
*
|
||||
* @return {string}
|
||||
* @readonly
|
||||
* @memberof Share
|
||||
*/
|
||||
get passwordExpirationTime() {
|
||||
return this._share.password_expiration_time
|
||||
}
|
||||
|
||||
/**
|
||||
* Password expiration time
|
||||
*
|
||||
* @param {string} password exipration time
|
||||
* @memberof Share
|
||||
*/
|
||||
set passwordExpirationTime(passwordExpirationTime) {
|
||||
this._share.password_expiration_time = passwordExpirationTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Password protection by Talk of the share
|
||||
*
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ class ShareByMailProvider implements IShareProvider {
|
|||
|
||||
// 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 ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true || $share->getSendPasswordByTalk()) {
|
||||
if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === false || $share->getSendPasswordByTalk()) {
|
||||
$send = $this->sendPassword($share, $password);
|
||||
if ($passwordEnforced && $send === false) {
|
||||
$this->sendPasswordToOwner($share, $password);
|
||||
|
|
@ -503,6 +503,13 @@ class ShareByMailProvider implements IShareProvider {
|
|||
$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
|
||||
$emailTemplate->addBodyText($password);
|
||||
|
||||
if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
|
||||
$expirationTime = new \DateTime();
|
||||
$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
|
||||
$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
|
||||
$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
|
||||
}
|
||||
|
||||
// The "From" contains the sharers name
|
||||
$instanceName = $this->defaults->getName();
|
||||
$senderName = $instanceName;
|
||||
|
|
@ -627,7 +634,16 @@ class ShareByMailProvider implements IShareProvider {
|
|||
$emailTemplate->addBodyText($bodyPart);
|
||||
$emailTemplate->addBodyText($this->l->t('This is the password:'));
|
||||
$emailTemplate->addBodyText($password);
|
||||
|
||||
if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
|
||||
$expirationTime = new \DateTime();
|
||||
$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
|
||||
$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
|
||||
$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
|
||||
}
|
||||
|
||||
$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
|
||||
|
||||
$emailTemplate->addFooter();
|
||||
|
||||
$instanceName = $this->defaults->getName();
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtection() {
|
||||
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword() {
|
||||
$share = $this->getMockBuilder(IShare::class)->getMock();
|
||||
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
|
||||
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
|
||||
|
|
@ -285,7 +285,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword() {
|
||||
public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithoutPermanentPassword() {
|
||||
$share = $this->getMockBuilder(IShare::class)->getMock();
|
||||
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
|
||||
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
|
||||
|
|
@ -310,21 +310,16 @@ class ShareByMailProviderTest extends TestCase {
|
|||
// The given password (but not the autogenerated password) should be
|
||||
// mailed to the receiver of the share because permanent passwords are 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(true);
|
||||
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
|
||||
$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');
|
||||
$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->assertSame('shareObject',
|
||||
$instance->create($share)
|
||||
|
|
@ -363,7 +358,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
|
||||
// The autogenerated password should be mailed to the receiver of the share because permanent passwords are enforced.
|
||||
$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
|
||||
$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(true);
|
||||
$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
|
||||
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
|
||||
|
||||
$message = $this->createMock(IMessage::class);
|
||||
|
|
@ -408,7 +403,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
// The given password (but not the autogenerated password) should be
|
||||
// mailed to the receiver of the share.
|
||||
$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
|
||||
$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(true);
|
||||
$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
|
||||
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
|
||||
$instance->expects($this->never())->method('autoGeneratePassword');
|
||||
|
||||
|
|
@ -429,7 +424,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function testCreateSendPasswordByTalkWithEnforcedPasswordProtection() {
|
||||
public function testCreateSendPasswordByTalkWithEnforcedPasswordProtectionWithPermanentPassword() {
|
||||
$share = $this->getMockBuilder(IShare::class)->getMock();
|
||||
$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@example.com');
|
||||
$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(true);
|
||||
|
|
@ -453,7 +448,7 @@ class ShareByMailProviderTest extends TestCase {
|
|||
|
||||
// The autogenerated password should be mailed to the owner of the share.
|
||||
$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
|
||||
$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
|
||||
$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
|
||||
$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
|
||||
$instance->expects($this->once())->method('autoGeneratePassword')->with($share)->willReturn('autogeneratedPassword');
|
||||
|
||||
|
|
|
|||
|
|
@ -61,23 +61,20 @@
|
|||
|
||||
<!-- request password button -->
|
||||
<?php if (!isset($_['identityOk']) && $_['share']->getShareType() === $_['share']::TYPE_EMAIL && !$_['share']->getSendPasswordByTalk()): ?>
|
||||
<input type="button"
|
||||
id="request-password-button-not-talk"
|
||||
value="<?php p($l->t('Request password')); ?>"
|
||||
class="primary" />
|
||||
<a id="request-password-button-not-talk"><?php p($l->t('Forgot password?')); ?></a>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- back to showShare button -->
|
||||
<form method="get">
|
||||
<fieldset>
|
||||
<input type="submit"
|
||||
<a
|
||||
href=""
|
||||
id="request-password-back-button"
|
||||
value="<?php p($l->t('Back')); ?>"
|
||||
class="primary"
|
||||
<?php if (isset($_['identityOk'])): ?>
|
||||
style="display:block;" />
|
||||
style="display:block;">
|
||||
<?php else: ?>
|
||||
style="display:none;" />
|
||||
style="display:none;">
|
||||
<?php endif; ?>
|
||||
<?php p($l->t('Back')); ?></a>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
|
|||
4
dist/files_sharing-files_sharing_tab.js
vendored
4
dist/files_sharing-files_sharing_tab.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-files_sharing_tab.js.map
vendored
2
dist/files_sharing-files_sharing_tab.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue