summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/css/files.css1
-rw-r--r--apps/sharebymail/appinfo/app.php7
-rw-r--r--apps/sharebymail/appinfo/info.xml6
-rw-r--r--apps/sharebymail/lib/Activity.php358
-rw-r--r--apps/sharebymail/tests/ActivityTest.php68
-rw-r--r--core/js/js.js2
-rw-r--r--core/js/oc-dialogs.js2
-rw-r--r--core/js/sharedialogshareelistview.js24
-rw-r--r--lib/private/Authentication/Token/DefaultTokenProvider.php1
-rw-r--r--lib/private/HintException.php32
-rw-r--r--lib/private/User/Session.php2
-rw-r--r--tests/lib/Authentication/Token/DefaultTokenProviderTest.php12
-rw-r--r--tests/lib/User/SessionTest.php46
13 files changed, 285 insertions, 276 deletions
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 1983d51809c..96b883bbc62 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -547,6 +547,7 @@ html.ie8 #fileList tr.selected td.filename>.selectCheckBox {
.bubble,
#app-navigation .app-navigation-entry-menu {
border-top-right-radius: 3px;
+ min-width: 100px;
}
.bubble:after,
#app-navigation .app-navigation-entry-menu:after {
diff --git a/apps/sharebymail/appinfo/app.php b/apps/sharebymail/appinfo/app.php
index 0723b2dcc5f..5ef7b6f18cb 100644
--- a/apps/sharebymail/appinfo/app.php
+++ b/apps/sharebymail/appinfo/app.php
@@ -22,10 +22,3 @@
$settings = new \OCA\ShareByMail\Settings();
\OCP\Util::connectHook('\OCP\Config', 'js', $settings, 'announceShareProvider');
-
-\OC::$server->getActivityManager()->registerExtension(function() {
- return new \OCA\ShareByMail\Activity(
- \OC::$server->query('L10NFactory'),
- \OC::$server->getActivityManager()
- );
-});
diff --git a/apps/sharebymail/appinfo/info.xml b/apps/sharebymail/appinfo/info.xml
index 6c4882d349f..1b3aa01bc67 100644
--- a/apps/sharebymail/appinfo/info.xml
+++ b/apps/sharebymail/appinfo/info.xml
@@ -12,4 +12,10 @@
<nextcloud min-version="11" max-version="11" />
</dependencies>
<default_enable/>
+
+ <activity>
+ <providers>
+ <provider>OCA\ShareByMail\Activity</provider>
+ </providers>
+ </activity>
</info>
diff --git a/apps/sharebymail/lib/Activity.php b/apps/sharebymail/lib/Activity.php
index 0b73d73c04c..58ab0a5cdcd 100644
--- a/apps/sharebymail/lib/Activity.php
+++ b/apps/sharebymail/lib/Activity.php
@@ -1,6 +1,6 @@
<?php
/**
- * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
@@ -19,251 +19,243 @@
*
*/
-
namespace OCA\ShareByMail;
-
-use OCP\Activity\IExtension;
+use OCP\Activity\IEvent;
use OCP\Activity\IManager;
+use OCP\Activity\IProvider;
+use OCP\Contacts\IManager as IContactsManager;
use OCP\IL10N;
-use OCP\L10N\IFactory;
-
-class Activity implements IExtension {
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\IUserManager;
- const SHARE_BY_MAIL_APP = 'sharebymail';
+class Activity implements IProvider {
- const SUBJECT_SHARED_EMAIL_SELF = 'shared_with_email_self';
- const SUBJECT_SHARED_EMAIL_BY = 'shared_with_email_by';
+ /** @var IL10N */
+ protected $l;
- /** @var IFactory */
- private $languageFactory;
+ /** @var IURLGenerator */
+ protected $url;
/** @var IManager */
- private $activityManager;
+ protected $activityManager;
- /**
- * @param IFactory $languageFactory
- * @param IManager $activityManager
- */
- public function __construct(IFactory $languageFactory, IManager $activityManager) {
- $this->languageFactory = $languageFactory;
- $this->activityManager = $activityManager;
- }
+ /** @var IUserManager */
+ protected $userManager;
+ /** @var IContactsManager */
+ protected $contactsManager;
- /**
- * The extension can return an array of additional notification types.
- * If no additional types are to be added false is to be returned
- *
- * @param string $languageCode
- * @return array|false Array "stringID of the type" => "translated string description for the setting"
- * or Array "stringID of the type" => [
- * 'desc' => "translated string description for the setting"
- * 'methods' => [self::METHOD_*],
- * ]
- * @since 8.0.0 - 8.2.0: Added support to allow limiting notifications to certain methods
- */
- public function getNotificationTypes($languageCode) {
- return false;
- }
+ /** @var array */
+ protected $displayNames = [];
- /**
- * For a given method additional types to be displayed in the settings can be returned.
- * In case no additional types are to be added false is to be returned.
- *
- * @param string $method
- * @return array|false
- * @since 8.0.0
- */
- public function getDefaultTypes($method) {
- return false;
- }
+ /** @var array */
+ protected $contactNames = [];
+
+ const SUBJECT_SHARED_EMAIL_SELF = 'shared_with_email_self';
+ const SUBJECT_SHARED_EMAIL_BY = 'shared_with_email_by';
/**
- * A string naming the css class for the icon to be used can be returned.
- * If no icon is known for the given type false is to be returned.
- *
- * @param string $type
- * @return string|false
- * @since 8.0.0
+ * @param IL10N $l
+ * @param IURLGenerator $url
+ * @param IManager $activityManager
+ * @param IUserManager $userManager
+ * @param IContactsManager $contactsManager
*/
- public function getTypeIcon($type) {
- return false;
+ public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IContactsManager $contactsManager) {
+ $this->l = $l;
+ $this->url = $url;
+ $this->activityManager = $activityManager;
+ $this->userManager = $userManager;
+ $this->contactsManager = $contactsManager;
}
/**
- * The extension can translate a given message to the requested languages.
- * If no translation is available false is to be returned.
- *
- * @param string $app
- * @param string $text
- * @param array $params
- * @param boolean $stripPath
- * @param boolean $highlightParams
- * @param string $languageCode
- * @return string|false
- * @since 8.0.0
+ * @param IEvent $event
+ * @param IEvent|null $previousEvent
+ * @return IEvent
+ * @throws \InvalidArgumentException
+ * @since 11.0.0
*/
- public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
- if ($app !== self::SHARE_BY_MAIL_APP) {
- return false;
+ public function parse(IEvent $event, IEvent $previousEvent = null) {
+ if ($event->getApp() !== 'sharebymail') {
+ throw new \InvalidArgumentException();
}
- $l = $this->getL10N($languageCode);
-
if ($this->activityManager->isFormattingFilteredObject()) {
- $translation = $this->translateShort($text, $l, $params);
- if ($translation !== false) {
- return $translation;
+ try {
+ return $this->parseShortVersion($event);
+ } catch (\InvalidArgumentException $e) {
+ // Ignore and simply use the long version...
}
}
- return $this->translateLong($text, $l, $params);
+ return $this->parseLongVersion($event);
}
-
/**
- * The extension can define the type of parameters for translation
- *
- * Currently known types are:
- * * file => will strip away the path of the file and add a tooltip with it
- * * username => will add the avatar of the user
- *
- * @param string $app
- * @param string $text
- * @return array|false
- * @since 8.0.0
+ * @param IEvent $event
+ * @return IEvent
+ * @throws \InvalidArgumentException
+ * @since 11.0.0
*/
- public function getSpecialParameterList($app, $text) {
- if ($app === self::SHARE_BY_MAIL_APP) {
- switch ($text) {
- case self::SUBJECT_SHARED_EMAIL_BY:
- return [
- 0 => 'file',
- 1 => 'email',
- 2 => 'user',
- ];
- case self::SUBJECT_SHARED_EMAIL_SELF:
- return [
- 0 => 'file',
- 1 => 'email',
- ];
- }
+ public function parseShortVersion(IEvent $event) {
+ $parsedParameters = $this->getParsedParameters($event);
+
+ if ($event->getSubject() === self::SUBJECT_SHARED_EMAIL_SELF) {
+ $event->setParsedSubject($this->l->t('Shared with %1$s', [
+ $parsedParameters['email']['name'],
+ ]))
+ ->setRichSubject($this->l->t('Shared with {email}'), [
+ 'email' => $parsedParameters['email'],
+ ])
+ ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
+ } else if ($event->getSubject() === self::SUBJECT_SHARED_EMAIL_BY) {
+ $event->setParsedSubject($this->l->t('Shared with %1$s by %2$s', [
+ $parsedParameters['email']['name'],
+ $parsedParameters['actor']['name'],
+ ]))
+ ->setRichSubject($this->l->t('Shared with {email} by {actor}'), [
+ 'email' => $parsedParameters['email'],
+ 'actor' => $parsedParameters['actor'],
+ ])
+ ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
+
+ } else {
+ throw new \InvalidArgumentException();
}
- return false;
+ return $event;
}
/**
- * The extension can define the parameter grouping by returning the index as integer.
- * In case no grouping is required false is to be returned.
- *
- * @param array $activity
- * @return integer|false
- * @since 8.0.0
+ * @param IEvent $event
+ * @return IEvent
+ * @throws \InvalidArgumentException
+ * @since 11.0.0
*/
- public function getGroupParameter($activity) {
- if ($activity['app'] === self::SHARE_BY_MAIL_APP) {
- switch ($activity['subject']) {
- case self::SUBJECT_SHARED_EMAIL_BY:
- // Group by file name
- return 1;
- case self::SUBJECT_SHARED_EMAIL_SELF:
- // Group by user/group
- return 1;
- }
+ public function parseLongVersion(IEvent $event) {
+ $parsedParameters = $this->getParsedParameters($event);
+
+ if ($event->getSubject() === self::SUBJECT_SHARED_EMAIL_SELF) {
+ $event->setParsedSubject($this->l->t('You shared %1$s with %2$s by mail', [
+ $parsedParameters['file']['path'],
+ $parsedParameters['email']['name'],
+ ]))
+ ->setRichSubject($this->l->t('You shared {file} with {email} by mail'), $parsedParameters)
+ ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
+ } else if ($event->getSubject() === self::SUBJECT_SHARED_EMAIL_BY) {
+ $event->setParsedSubject($this->l->t('%3$s shared %1$s with %2$s by mail', [
+ $parsedParameters['file']['path'],
+ $parsedParameters['email']['name'],
+ $parsedParameters['actor']['name'],
+ ]))
+ ->setRichSubject($this->l->t('{actor} shared {file} with {email} by mail'), $parsedParameters)
+ ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/share.svg')));
+ } else {
+ throw new \InvalidArgumentException();
}
- return false;
-
+ return $event;
}
- /**
- * The extension can define additional navigation entries. The array returned has to contain two keys 'top'
- * and 'apps' which hold arrays with the relevant entries.
- * If no further entries are to be added false is no be returned.
- *
- * @return array|false
- * @since 8.0.0
- */
- public function getNavigation() {
- return false;
+ protected function getParsedParameters(IEvent $event) {
+ $subject = $event->getSubject();
+ $parameters = $event->getSubjectParameters();
+
+ switch ($subject) {
+ case self::SUBJECT_SHARED_EMAIL_SELF:
+ return [
+ 'file' => $this->generateFileParameter((int) $event->getObjectId(), $parameters[0]),
+ 'email' => $this->generateEmailParameter($parameters[1]),
+ ];
+ case self::SUBJECT_SHARED_EMAIL_BY:
+ return [
+ 'file' => $this->generateFileParameter((int) $event->getObjectId(), $parameters[0]),
+ 'email' => $this->generateEmailParameter($parameters[1]),
+ 'actor' => $this->generateUserParameter($parameters[2]),
+ ];
+ }
+ throw new \InvalidArgumentException();
}
/**
- * The extension can check if a customer filter (given by a query string like filter=abc) is valid or not.
- *
- * @param string $filterValue
- * @return boolean
- * @since 8.0.0
+ * @param int $id
+ * @param string $path
+ * @return array
*/
- public function isFilterValid($filterValue) {
- return false;
+ protected function generateFileParameter($id, $path) {
+ return [
+ 'type' => 'file',
+ 'id' => $id,
+ 'name' => basename($path),
+ 'path' => $path,
+ 'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $id]),
+ ];
}
/**
- * The extension can filter the types based on the filter if required.
- * In case no filter is to be applied false is to be returned unchanged.
- *
- * @param array $types
- * @param string $filter
- * @return array|false
- * @since 8.0.0
+ * @param string $email
+ * @return array
*/
- public function filterNotificationTypes($types, $filter) {
- return false;
+ protected function generateEmailParameter($email) {
+ if (!isset($this->contactNames[$email])) {
+ $this->contactNames[$email] = $this->getContactName($email);
+ }
+
+ return [
+ 'type' => 'email',
+ 'id' => $email,
+ 'name' => $this->contactNames[$email],
+ ];
}
/**
- * For a given filter the extension can specify the sql query conditions including parameters for that query.
- * In case the extension does not know the filter false is to be returned.
- * The query condition and the parameters are to be returned as array with two elements.
- * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%'));
- *
- * @param string $filter
- * @return array|false
- * @since 8.0.0
+ * @param string $uid
+ * @return array
*/
- public function getQueryForFilter($filter) {
- return false;
- }
+ protected function generateUserParameter($uid) {
+ if (!isset($this->displayNames[$uid])) {
+ $this->displayNames[$uid] = $this->getDisplayName($uid);
+ }
- protected function getL10N($languageCode = null) {
- return $this->languageFactory->get(self::SHARE_BY_MAIL_APP, $languageCode);
+ return [
+ 'type' => 'user',
+ 'id' => $uid,
+ 'name' => $this->displayNames[$uid],
+ ];
}
/**
- * @param string $text
- * @param IL10N $l
- * @param array $params
- * @return bool|string
+ * @param string $email
+ * @return string
*/
- protected function translateLong($text, IL10N $l, array $params) {
+ protected function getContactName($email) {
+ $addressBookContacts = $this->contactsManager->search($email, ['EMAIL']);
- switch ($text) {
- case self::SUBJECT_SHARED_EMAIL_SELF:
- return (string) $l->t('You shared %1$s with %2$s by mail', $params);
- case self::SUBJECT_SHARED_EMAIL_BY:
- return (string) $l->t('%3$s shared %1$s with %2$s by mail', $params);
+ foreach ($addressBookContacts as $contact) {
+ if (isset($contact['isLocalSystemBook'])) {
+ continue;
+ }
+
+ if (in_array($email, $contact['EMAIL'])) {
+ return $contact['FN'];
+ }
}
- return false;
+ return $email;
}
/**
- * @param string $text
- * @param IL10N $l
- * @param array $params
- * @return bool|string
+ * @param string $uid
+ * @return string
*/
- protected function translateShort($text, IL10N $l, array $params) {
- switch ($text) {
- case self::SUBJECT_SHARED_EMAIL_SELF:
- return (string) $l->t('Shared with %2$s', $params);
- case self::SUBJECT_SHARED_EMAIL_BY:
- return (string) $l->t('Shared with %3$s by %2$s', $params);
+ protected function getDisplayName($uid) {
+ $user = $this->userManager->get($uid);
+ if ($user instanceof IUser) {
+ return $user->getDisplayName();
+ } else {
+ return $uid;
}
-
- return false;
}
-
}
diff --git a/apps/sharebymail/tests/ActivityTest.php b/apps/sharebymail/tests/ActivityTest.php
deleted file mode 100644
index 9bc8c827da9..00000000000
--- a/apps/sharebymail/tests/ActivityTest.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-namespace OCA\ShareByMail\Tests;
-
-
-use OCA\ShareByMail\Activity;
-
-class ActivityTest extends \Test\TestCase {
-
- /**
- * @var \OCA\ShareByMail\Activity
- */
- private $activity;
-
- protected function setUp() {
- parent::setUp();
- $this->activity = new Activity(
- $this->getMockBuilder('OCP\L10N\IFactory')
- ->disableOriginalConstructor()
- ->getMock(),
- $this->getMockBuilder('OCP\Activity\IManager')
- ->disableOriginalConstructor()
- ->getMock()
- );
- }
-
- /**
- * @dataProvider dataTestGetSpecialParameterList
- *
- */
- public function testGetSpecialParameterList($app, $text, $expected) {
- $result = $this->activity->getSpecialParameterList($app, $text);
- $this->assertSame($expected, $result);
- }
-
- public function dataTestGetSpecialParameterList() {
- return [
- ['sharebymail', Activity::SUBJECT_SHARED_EMAIL_SELF, [0 => 'file', 1 => 'email']],
- ['sharebymail', Activity::SUBJECT_SHARED_EMAIL_BY, [0 => 'file', 1 => 'email', 2 => 'user']],
- ['sharebymail', 'unknown', false],
- ['randomApp', Activity::SUBJECT_SHARED_EMAIL_SELF, false],
- ['randomApp', Activity::SUBJECT_SHARED_EMAIL_BY, false],
-
- ];
- }
-
-}
-
diff --git a/core/js/js.js b/core/js/js.js
index b8535518f02..e2b8731c877 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1502,7 +1502,7 @@ function initCore() {
$(window).resize(_.debounce(adjustControlsWidth, 250));
- $('body').delegate('#app-content', 'apprendered appresized', adjustControlsWidth);
+ $('body').delegate('#app-content', 'apprendered appresized', _.debounce(adjustControlsWidth, 100));
}
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js
index 3b5c1ae7199..f811322b099 100644
--- a/core/js/oc-dialogs.js
+++ b/core/js/oc-dialogs.js
@@ -168,7 +168,7 @@ var OCdialogs = {
return;
}
this.filepicker.loading = true;
- this.filepicker.filesClient = OC.Files.getClient();
+ this.filepicker.filesClient = (OCA.Sharing && OCA.Sharing.PublicApp && OCA.Sharing.PublicApp.fileList)? OCA.Sharing.PublicApp.fileList.filesClient: OC.Files.getClient();
$.when(this._getFilePickerTemplate()).then(function($tmpl) {
self.filepicker.loading = false;
var dialogName = 'oc-dialog-filepicker-content';
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 96bbf94fa1c..226f18b2d76 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -34,7 +34,6 @@
'</span>' +
'{{/unless}}' +
'{{/if}}' +
- '{{#unless isMailShare}}' +
'<a href="#"><span class="icon icon-more"></span></a>' +
'<div class="popovermenu bubble hidden menu">' +
'<ul>' +
@@ -47,37 +46,36 @@
'</li>' +
'{{/unless}} {{/if}} {{/if}}' +
'{{#if isFolder}}' +
- '{{#if createPermissionPossible}}' +
+ '{{#if createPermissionPossible}}{{#unless isMailShare}}' +
'<li>' +
'<span class="shareOption">' +
'<input id="canCreate-{{cid}}-{{shareWith}}" type="checkbox" name="create" class="permissions checkbox" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/>' +
'<label for="canCreate-{{cid}}-{{shareWith}}">{{createPermissionLabel}}</label>' +
'</span>' +
'</li>' +
- '{{/if}}' +
- '{{#if updatePermissionPossible}}' +
+ '{{/unless}}{{/if}}' +
+ '{{#if updatePermissionPossible}}{{#unless isMailShare}}' +
'<li>' +
'<span class="shareOption">' +
'<input id="canUpdate-{{cid}}-{{shareWith}}" type="checkbox" name="update" class="permissions checkbox" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/>' +
'<label for="canUpdate-{{cid}}-{{shareWith}}">{{updatePermissionLabel}}</label>' +
'</span>' +
'</li>' +
- '{{/if}}' +
- '{{#if deletePermissionPossible}}' +
+ '{{/unless}}{{/if}}' +
+ '{{#if deletePermissionPossible}}{{#unless isMailShare}}' +
'<li>' +
'<span class="shareOption">' +
'<input id="canDelete-{{cid}}-{{shareWith}}" type="checkbox" name="delete" class="permissions checkbox" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/>' +
'<label for="canDelete-{{cid}}-{{shareWith}}">{{deletePermissionLabel}}</label>' +
'</span>' +
'</li>' +
- '{{/if}}' +
+ '{{/unless}}{{/if}}' +
'{{/if}}' +
'<li>' +
'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
'</li>' +
'</ul>' +
'</div>' +
- '{{/unless}}' +
'</span>' +
'</li>' +
'{{/each}}' +
@@ -284,9 +282,13 @@
this.$('.popovermenu').on('afterHide', function() {
_this._menuOpen = false;
});
- if (this._menuOpen) {
+ if (this._menuOpen != false) {
// Open menu again if it was opened before
- OC.showMenu(null, this.$('.popovermenu'));
+ var shareId = parseInt(this._menuOpen, 10);
+ if(!_.isNaN(shareId)) {
+ var liSelector = 'li[data-share-id=' + shareId + ']';
+ OC.showMenu(null, this.$(liSelector + ' .popovermenu'));
+ }
}
this.delegateEvents();
@@ -344,7 +346,7 @@
var $menu = $li.find('.popovermenu');
OC.showMenu(null, $menu);
- this._menuOpen = true;
+ this._menuOpen = $li.data('share-id');
},
onPermissionChange: function(event) {
diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php
index ec4cc10c269..0e1196a9da4 100644
--- a/lib/private/Authentication/Token/DefaultTokenProvider.php
+++ b/lib/private/Authentication/Token/DefaultTokenProvider.php
@@ -192,6 +192,7 @@ class DefaultTokenProvider implements IProvider {
$newToken->setName($token->getName());
$newToken->setToken($this->hashToken($sessionId));
$newToken->setType(IToken::TEMPORARY_TOKEN);
+ $newToken->setRemember($token->getRemember());
$newToken->setLastActivity($this->time->getTime());
$this->mapper->insert($newToken);
}
diff --git a/lib/private/HintException.php b/lib/private/HintException.php
index 7ff8240afd2..1233fdca148 100644
--- a/lib/private/HintException.php
+++ b/lib/private/HintException.php
@@ -26,19 +26,51 @@
namespace OC;
+/**
+ * Class HintException
+ *
+ * An Exception class with the intention to be presented to the end user
+ *
+ * @package OC
+ */
class HintException extends \Exception {
private $hint;
+ /**
+ * HintException constructor.
+ *
+ * @param string $message The error message. It will be not revealed to the
+ * the user (unless the hint is empty) and thus
+ * should be not translated.
+ * @param string $hint A useful message that is presented to the end
+ * user. It should be translated, but must not
+ * contain sensitive data.
+ * @param int $code
+ * @param \Exception|null $previous
+ */
public function __construct($message, $hint = '', $code = 0, \Exception $previous = null) {
$this->hint = $hint;
parent::__construct($message, $code, $previous);
}
+ /**
+ * Returns a string representation of this Exception that includes the error
+ * code, the message and the hint.
+ *
+ * @return string
+ */
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message} ({$this->hint})\n";
}
+ /**
+ * Returns the hint with the intention to be presented to the end user. If
+ * an empty hint was specified upon instatiation, the message is returned
+ * instead.
+ *
+ * @return string
+ */
public function getHint() {
if (empty($this->hint)) {
return $this->message;
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index a45b1dcd10f..c3561cf64e3 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -558,7 +558,7 @@ class Session implements IUserSession, Emitter {
try {
$sessionId = $this->session->getId();
$pwd = $this->getPassword($password);
- $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, IToken::REMEMBER);
+ $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
return true;
} catch (SessionNotAvailableException $ex) {
// This can happen with OCC, where a memory session is used
diff --git a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
index 8d92ee405a1..e354fcc7172 100644
--- a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
+++ b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php
@@ -292,6 +292,10 @@ class DefaultTokenProviderTest extends TestCase {
->expects($this->at(3))
->method('getName')
->willReturn('MyTokenName');
+ $token
+ ->expects($this->at(3))
+ ->method('getRememberMe')
+ ->willReturn(IToken::DO_NOT_REMEMBER);
$this->config
->expects($this->exactly(2))
->method('getSystemValue')
@@ -308,6 +312,7 @@ class DefaultTokenProviderTest extends TestCase {
$newToken->setName('MyTokenName');
$newToken->setToken(hash('sha512', 'newId' . 'MyInstanceSecret'));
$newToken->setType(IToken::TEMPORARY_TOKEN);
+ $newToken->setRemember(IToken::DO_NOT_REMEMBER);
$newToken->setLastActivity(1313131);
$this->mapper
->expects($this->at(1))
@@ -342,6 +347,10 @@ class DefaultTokenProviderTest extends TestCase {
->expects($this->at(4))
->method('getName')
->willReturn('MyTokenName');
+ $token
+ ->expects($this->at(3))
+ ->method('getRememberMe')
+ ->willReturn(IToken::REMEMBER);
$this->crypto
->expects($this->any(0))
->method('decrypt')
@@ -368,12 +377,13 @@ class DefaultTokenProviderTest extends TestCase {
$newToken->setName('MyTokenName');
$newToken->setToken(hash('sha512', 'newId' . 'MyInstanceSecret'));
$newToken->setType(IToken::TEMPORARY_TOKEN);
+ $newToken->setRemember(IToken::REMEMBER);
$newToken->setLastActivity(1313131);
$newToken->setPassword('EncryptedPassword');
$this->mapper
->expects($this->at(1))
->method('insert')
- ->with($newToken);
+ ->with($this->equalTo($newToken));
$this->tokenProvider->renewSessionToken('oldId', 'newId');
}
diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php
index ee9ed737cf5..78b673d10bd 100644
--- a/tests/lib/User/SessionTest.php
+++ b/tests/lib/User/SessionTest.php
@@ -767,7 +767,6 @@ class SessionTest extends \Test\TestCase {
public function testCreateSessionToken() {
$manager = $this->createMock(Manager::class);
$session = $this->createMock(ISession::class);
- $token = $this->createMock(IToken::class);
$user = $this->createMock(IUser::class);
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random);
@@ -801,11 +800,52 @@ class SessionTest extends \Test\TestCase {
$this->tokenProvider->expects($this->once())
->method('generateToken')
- ->with($sessionId, $uid, $loginName, $password, 'Firefox');
+ ->with($sessionId, $uid, $loginName, $password, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::DO_NOT_REMEMBER);
$this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
}
+ public function testCreateRememberedSessionToken() {
+ $manager = $this->createMock(Manager::class);
+ $session = $this->createMock(ISession::class);
+ $user = $this->createMock(IUser::class);
+ $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random);
+
+ $random = $this->createMock(ISecureRandom::class);
+ $config = $this->createMock(IConfig::class);
+ $csrf = $this->getMockBuilder('\OC\Security\CSRF\CsrfTokenManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $request = new \OC\AppFramework\Http\Request([
+ 'server' => [
+ 'HTTP_USER_AGENT' => 'Firefox',
+ ]
+ ], $random, $config, $csrf);
+
+ $uid = 'user123';
+ $loginName = 'User123';
+ $password = 'passme';
+ $sessionId = 'abcxyz';
+
+ $manager->expects($this->once())
+ ->method('get')
+ ->with($uid)
+ ->will($this->returnValue($user));
+ $session->expects($this->once())
+ ->method('getId')
+ ->will($this->returnValue($sessionId));
+ $this->tokenProvider->expects($this->once())
+ ->method('getToken')
+ ->with($password)
+ ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
+
+ $this->tokenProvider->expects($this->once())
+ ->method('generateToken')
+ ->with($sessionId, $uid, $loginName, $password, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::REMEMBER);
+
+ $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password, true));
+ }
+
public function testCreateSessionTokenWithTokenPassword() {
$manager = $this->getMockBuilder('\OC\User\Manager')
->disableOriginalConstructor()
@@ -850,7 +890,7 @@ class SessionTest extends \Test\TestCase {
$this->tokenProvider->expects($this->once())
->method('generateToken')
- ->with($sessionId, $uid, $loginName, $realPassword, 'Firefox');
+ ->with($sessionId, $uid, $loginName, $realPassword, 'Firefox', IToken::TEMPORARY_TOKEN, IToken::DO_NOT_REMEMBER);
$this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password));
}