From f33c49e2be7be32af7090da77101b35743e87ee0 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 24 Jul 2014 12:50:39 +0200 Subject: - adding default value for $recoveryPassword - set password correctly in lost password --- core/lostpassword/controller/lostcontroller.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/lostpassword/controller/lostcontroller.php b/core/lostpassword/controller/lostcontroller.php index b1be65b4f01..e4d51fde077 100644 --- a/core/lostpassword/controller/lostcontroller.php +++ b/core/lostpassword/controller/lostcontroller.php @@ -20,13 +20,36 @@ use \OC\Core\LostPassword\EncryptedDataException; class LostController extends Controller { + /** + * @var \OCP\IURLGenerator + */ protected $urlGenerator; + + /** + * @var \OCP\IUserManager + */ protected $userManager; + + /** + * @var \OC_Defaults + */ protected $defaults; + + /** + * @var IL10N + */ protected $l10n; protected $from; protected $isDataEncrypted; + + /** + * @var IConfig + */ protected $config; + + /** + * @var IUserSession + */ protected $userSession; public function __construct($appName, @@ -110,7 +133,7 @@ class LostController extends Controller { throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid')); } - if (!$user->setPassword($userId, $password)) { + if (!$user->setPassword($password)) { throw new \Exception(); } -- cgit v1.2.3 From 2d7379da2c172fac069fdb2828e69bfd8a4b9be7 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 24 Jul 2014 14:38:19 +0200 Subject: improve look of search on mobile, save space in top bar --- core/css/icons.css | 3 +++ core/css/mobile.css | 16 +++++++++++----- core/img/actions/search-white.png | Bin 0 -> 309 bytes core/img/actions/search-white.svg | 5 +++++ 4 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 core/img/actions/search-white.png create mode 100644 core/img/actions/search-white.svg (limited to 'core') diff --git a/core/css/icons.css b/core/css/icons.css index 60f0b1b8c60..534c1c66514 100644 --- a/core/css/icons.css +++ b/core/css/icons.css @@ -136,6 +136,9 @@ .icon-search { background-image: url('../img/actions/search.svg'); } +.icon-search-white { + background-image: url('../img/actions/search-white.svg'); +} .icon-settings { background-image: url('../img/actions/settings.svg'); diff --git a/core/css/mobile.css b/core/css/mobile.css index 6e2172ddbb7..21090d08cb7 100644 --- a/core/css/mobile.css +++ b/core/css/mobile.css @@ -31,16 +31,22 @@ /* compress search box on mobile, expand when focused */ .searchbox input[type="search"] { - width: 15%; - -webkit-transition: width 100ms; - -moz-transition: width 100ms; - -o-transition: width 100ms; - transition: width 100ms; + width: 0; + cursor: pointer; + background-color: transparent; + background-image: url('../img/actions/search-white.svg'); + -webkit-transition: all 100ms; + -moz-transition: all 100ms; + -o-transition: all 100ms; + transition: all 100ms; } .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active { width: 155px; max-width: 50%; + cursor: text; + background-color: #fff; + background-image: url('../img/actions/search.svg'); } /* do not show display name on mobile when profile picture is present */ diff --git a/core/img/actions/search-white.png b/core/img/actions/search-white.png new file mode 100644 index 00000000000..9812c44a3d6 Binary files /dev/null and b/core/img/actions/search-white.png differ diff --git a/core/img/actions/search-white.svg b/core/img/actions/search-white.svg new file mode 100644 index 00000000000..9b312d0460d --- /dev/null +++ b/core/img/actions/search-white.svg @@ -0,0 +1,5 @@ + + + + + -- cgit v1.2.3 From 7cd1a48222b6e9c3b42df563b24e79f5a26a683f Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 24 Jul 2014 14:03:40 +0200 Subject: enable input grouping also outside of log in screen --- core/css/styles.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/css/styles.css b/core/css/styles.css index 40c1622ca26..17ed3fbc74c 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -444,13 +444,15 @@ input[name='password-clone'] { .groupbottom { position: relative; } -#body-login .grouptop input { +#body-login .grouptop input, +.grouptop input { margin-bottom: 0; border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; } -#body-login .groupmiddle input { +#body-login .groupmiddle input, +.groupmiddle input { margin-top: 0; margin-bottom: 0; border-top: 0; @@ -458,7 +460,8 @@ input[name='password-clone'] { border-radius: 0; box-shadow: 0 1px 0 rgba(0,0,0,.1) inset !important; } -#body-login .groupbottom input { +#body-login .groupbottom input, +.groupbottom input { margin-top: 0; border-top: 0; border-top-right-radius: 0; -- cgit v1.2.3 From 2e28b7fff982aff352f82bafa1e2cf4ec23956ff Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 23 Jul 2014 16:42:33 +0200 Subject: add OCS api call to set expire date for link shares --- apps/files_sharing/lib/api.php | 27 ++++++++++++++- apps/files_sharing/tests/api.php | 74 +++++++++++++++++++++++++++++++++++++++- core/ajax/share.php | 16 +++------ lib/private/share/share.php | 59 +++++++++++++++++++++++++++++--- lib/private/util.php | 19 +++++++++-- lib/public/share.php | 5 +-- lib/public/util.php | 9 +++++ tests/lib/share/share.php | 48 ++++++++++++++++++++------ 8 files changed, 224 insertions(+), 33 deletions(-) (limited to 'core') diff --git a/apps/files_sharing/lib/api.php b/apps/files_sharing/lib/api.php index 50ba74f5beb..368e3172c6b 100644 --- a/apps/files_sharing/lib/api.php +++ b/apps/files_sharing/lib/api.php @@ -339,6 +339,8 @@ class Api { return self::updatePassword($share, $params); } elseif (isset($params['_put']['publicUpload'])) { return self::updatePublicUpload($share, $params); + } elseif (isset($params['_put']['expireDate'])) { + return self::updateExpireDate($share, $params); } } catch (\Exception $e) { @@ -420,6 +422,29 @@ class Api { } + /** + * set expire date for public link share + * @param array $share information about the share + * @param array $params contains 'expireDate' which needs to be a well formated date string, e.g DD-MM-YYYY + * @return \OC_OCS_Result + */ + private static function updateExpireDate($share, $params) { + // only public links can have a expire date + if ((int)$share['share_type'] !== \OCP\Share::SHARE_TYPE_LINK ) { + return new \OC_OCS_Result(null, 404, "expire date only exists for public link shares"); + } + + try { + $expireDateSet = \OCP\Share::setExpirationDate($share['item_type'], $share['item_source'], $params['_put']['expireDate'], (int)$share['stime']); + $result = ($expireDateSet) ? new \OC_OCS_Result() : new \OC_OCS_Result(null, 404, "couldn't set expire date"); + } catch (\Exception $e) { + $result = new \OC_OCS_Result(null, 404, $e->getMessage()); + } + + return $result; + + } + /** * update password for public link share * @param array $share information about the share @@ -555,7 +580,7 @@ class Api { * @return array with: item_source, share_type, share_with, item_type, permissions */ private static function getShareFromId($shareID) { - $sql = 'SELECT `file_source`, `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; + $sql = 'SELECT `file_source`, `item_source`, `share_type`, `share_with`, `item_type`, `permissions`, `stime` FROM `*PREFIX*share` WHERE `id` = ?'; $args = array($shareID); $query = \OCP\DB::prepare($sql); $result = $query->execute($args); diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php index 72dd5816ea0..49571d4c3c2 100644 --- a/apps/files_sharing/tests/api.php +++ b/apps/files_sharing/tests/api.php @@ -938,6 +938,78 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } + /** + * @medium + */ + function testUpdateShareExpireDate() { + + $fileInfo = $this->view->getFileInfo($this->folder); + + // enforce expire date, by default 7 days after the file was shared + \OCP\Config::setAppValue('core', 'shareapi_default_expire_date', 'yes'); + \OCP\Config::setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); + + $dateWithinRange = new \DateTime(); + $dateWithinRange->add(new \DateInterval('P5D')); + $dateOutOfRange = new \DateTime(); + $dateOutOfRange->add(new \DateInterval('P8D')); + + $result = \OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, + null, 1); + + // share was successful? + $this->assertTrue(is_string($result)); + + $items = \OCP\Share::getItemShared('file', null); + + // make sure that we found a link share + $this->assertEquals(1, count($items)); + + $linkShare = reset($items); + + // update expire date to a valid value + $params = array(); + $params['id'] = $linkShare['id']; + $params['_put'] = array(); + $params['_put']['expireDate'] = $dateWithinRange->format('Y-m-d'); + + $result = Share\Api::updateShare($params); + + $this->assertTrue($result->succeeded()); + + $items = \OCP\Share::getItemShared('file', $linkShare['file_source']); + + $updatedLinkShare = reset($items); + + // date should be changed + $this->assertTrue(is_array($updatedLinkShare)); + $this->assertEquals($dateWithinRange->format('Y-m-d') . ' 00:00:00', $updatedLinkShare['expiration']); + + // update expire date to a value out of range + $params = array(); + $params['id'] = $linkShare['id']; + $params['_put'] = array(); + $params['_put']['expireDate'] = $dateOutOfRange->format('Y-m-d'); + + $result = Share\Api::updateShare($params); + + $this->assertFalse($result->succeeded()); + + $items = \OCP\Share::getItemShared('file', $linkShare['file_source']); + + $updatedLinkShare = reset($items); + + // date shouldn't be changed + $this->assertTrue(is_array($updatedLinkShare)); + $this->assertEquals($dateWithinRange->format('Y-m-d') . ' 00:00:00', $updatedLinkShare['expiration']); + + // cleanup + \OCP\Config::setAppValue('core', 'shareapi_default_expire_date', 'no'); + \OCP\Config::setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null); + + } + /** * @medium * @depends testCreateShare @@ -1158,7 +1230,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); $this->assertTrue($result); - $result = \OCP\Share::setExpirationDate('file', $info->getId() , $expireDate); + $result = \OCP\Share::setExpirationDate('file', $info->getId() , $expireDate, $now); $this->assertTrue($result); //manipulate stime so that both shares are older then the default expire date diff --git a/core/ajax/share.php b/core/ajax/share.php index be72e36541a..4b5a6cd664f 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -80,18 +80,12 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo break; case 'setExpirationDate': if (isset($_POST['date'])) { - $l = OC_L10N::get('core'); - $date = new \DateTime($_POST['date']); - $today = new \DateTime('now'); - - - - if ($date < $today) { - OC_JSON::error(array('data' => array('message' => $l->t('Expiration date is in the past.')))); - return; + try { + $return = OCP\Share::setExpirationDate($_POST['itemType'], $_POST['itemSource'], $_POST['date']); + ($return) ? OC_JSON::success() : OC_JSON::error(); + } catch (\Exception $e) { + OC_JSON::error(array('data' => array('message' => $e->getMessage()))); } - $return = OCP\Share::setExpirationDate($_POST['itemType'], $_POST['itemSource'], $_POST['date']); - ($return) ? OC_JSON::success() : OC_JSON::error(); } break; case 'informRecipients': diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 673c0dc383a..af286e7154e 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -924,20 +924,70 @@ class Share extends \OC\Share\Constants { throw new \Exception($message_t); } + /** + * validate expire date if it meets all constraints + * + * @param string $expireDate well formate date string, e.g. "DD-MM-YYYY" + * @param string $shareTime timestamp when the file was shared + * @param string $itemType + * @param string $itemSource + * @return DateTime validated date + * @throws \Exception + */ + private static function validateExpireDate($expireDate, $shareTime, $itemType, $itemSource) { + $l = \OC_L10N::get('lib'); + $date = new \DateTime($expireDate); + $today = new \DateTime('now'); + + // if the user doesn't provide a share time we need to get it from the database + // fall-back mode to keep API stable, because the $shareTime parameter was added later + $defaultExpireDateEnforced = \OCP\Util::isDefaultExpireDateEnforced(); + if ($defaultExpireDateEnforced && $shareTime === null) { + $items = self::getItemShared($itemType, $itemSource); + $firstItem = reset($items); + $shareTime = (int)$firstItem['stime']; + } + + if ($defaultExpireDateEnforced) { + // initialize max date with share time + $maxDate = new \DateTime(); + $maxDate->setTimestamp($shareTime); + $maxDays = \OCP\Config::getAppValue('core', 'shareapi_expire_after_n_days', '7'); + $maxDate->add(new \DateInterval('P' . $maxDays . 'D')); + if ($date > $maxDate) { + $warning = 'Can not set expire date. Shares can not expire later then ' . $maxDays . ' after they where shared'; + $warning_t = $l->t('Can not set expire date. Shares can not expire later then %s after they where shared', array($maxDays)); + \OCP\Util::writeLog('OCP\Share', $warning, \OCP\Util::WARN); + throw new \Exception($warning_t); + } + } + + if ($date < $today) { + $message = 'Can not set expire date. Expire date is in the past'; + $message_t = $l->t('Can not set expire date. Expire date is in the past'); + \OCP\Util::writeLog('OCP\Share', $message, \OCP\Util::WARN); + throw new \Exception($message_t); + } + + return $date; + } + /** * Set expiration date for a share * @param string $itemType * @param string $itemSource * @param string $date expiration date + * @param int $shareTime timestamp from when the file was shared + * @throws \Exception * @return boolean */ - public static function setExpirationDate($itemType, $itemSource, $date) { + public static function setExpirationDate($itemType, $itemSource, $date, $shareTime = null) { $user = \OC_User::getUser(); if ($date == '') { $date = null; } else { - $date = new \DateTime($date); + $date = self::validateExpireDate($date, $shareTime, $itemType, $itemSource); } $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `item_type` = ? AND `item_source` = ? AND `uid_owner` = ? AND `share_type` = ?'); $query->bindValue(1, $date, 'datetime'); @@ -954,11 +1004,10 @@ class Share extends \OC\Share\Constants { 'date' => $date, 'uidOwner' => $user )); - + return true; + } - } - /** * Checks whether a share has expired, calls unshareItem() if yes. * @param array $item Share data (usually database row) diff --git a/lib/private/util.php b/lib/private/util.php index 67da7a2f63f..896b076afa6 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -22,7 +22,7 @@ class OC_Util { self::$rootMounted = true; } } - + /** * mounting an object storage as the root fs will in essence remove the * necessity of a data folder being present. @@ -50,7 +50,7 @@ class OC_Util { self::$rootMounted = true; } } - + /** * Can be set up * @param string $user @@ -170,6 +170,21 @@ class OC_Util { return false; } + /** + * check if share API enforces a default expire date + * @return boolean + */ + public static function isDefaultExpireDateEnforced() { + $isDefaultExpireDateEnabled = \OCP\Config::getAppValue('core', 'shareapi_default_expire_date', 'no'); + $enforceDefaultExpireDate = false; + if ($isDefaultExpireDateEnabled === 'yes') { + $value = \OCP\Config::getAppValue('core', 'shareapi_enforce_expire_date', 'no'); + $enforceDefaultExpireDate = ($value === 'yes') ? true : false; + } + + return $enforceDefaultExpireDate; + } + /** * Get the quota of a user * @param string $user diff --git a/lib/public/share.php b/lib/public/share.php index 8566a38c61e..c0939dce53f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -298,10 +298,11 @@ class Share extends \OC\Share\Constants { * @param string $itemType * @param string $itemSource * @param string $date expiration date + * @param int $shareTime timestamp from when the file was shared * @return boolean */ - public static function setExpirationDate($itemType, $itemSource, $date) { - return \OC\Share\Share::setExpirationDate($itemType, $itemSource, $date); + public static function setExpirationDate($itemType, $itemSource, $date, $shareTime = null) { + return \OC\Share\Share::setExpirationDate($itemType, $itemSource, $date, $shareTime); } /** diff --git a/lib/public/util.php b/lib/public/util.php index 8f4691eeade..2a6e977f085 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -517,6 +517,15 @@ class Util { return \OC_Util::isPublicLinkPasswordRequired(); } + /** + * check if share API enforces a default expire date + * @return boolean + */ + public static function isDefaultExpireDateEnforced() { + return \OC_Util::isDefaultExpireDateEnforced(); + } + + /** * Checks whether the current version needs upgrade. * diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index 5920b44a8e0..0e3dfe8291d 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -326,10 +326,14 @@ class Test_Share extends PHPUnit_Framework_TestCase { $this->shareUserOneTestFileWithUserTwo(); $this->shareUserTestFileAsLink(); - $this->assertTrue( - OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInPast), - 'Failed asserting that user 1 successfully set an expiration date for the test.txt share.' - ); + // manipulate share table and set expire date to the past + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `item_type` = ? AND `item_source` = ? AND `uid_owner` = ? AND `share_type` = ?'); + $query->bindValue(1, new \DateTime($this->dateInPast), 'datetime'); + $query->bindValue(2, 'test'); + $query->bindValue(3, 'test.txt'); + $query->bindValue(4, $this->user1); + $query->bindValue(5, \OCP\Share::SHARE_TYPE_LINK); + $query->execute(); $shares = OCP\Share::getItemsShared('test'); $this->assertSame(1, count($shares)); @@ -337,6 +341,24 @@ class Test_Share extends PHPUnit_Framework_TestCase { $this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share['share_type']); } + public function testSetExpireDateInPast() { + OC_User::setUserId($this->user1); + $this->shareUserOneTestFileWithUserTwo(); + $this->shareUserTestFileAsLink(); + + $setExpireDateFailed = false; + try { + $this->assertTrue( + OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInPast, ''), + 'Failed asserting that user 1 successfully set an expiration date for the test.txt share.' + ); + } catch (\Exception $e) { + $setExpireDateFailed = true; + } + + $this->assertTrue($setExpireDateFailed); + } + public function testShareWithUserExpirationValid() { OC_User::setUserId($this->user1); $this->shareUserOneTestFileWithUserTwo(); @@ -344,7 +366,7 @@ class Test_Share extends PHPUnit_Framework_TestCase { $this->assertTrue( - OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInFuture), + OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInFuture, ''), 'Failed asserting that user 1 successfully set an expiration date for the test.txt share.' ); @@ -552,7 +574,7 @@ class Test_Share extends PHPUnit_Framework_TestCase { // testGetShareByTokenExpirationValid $this->assertTrue( - OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInFuture), + OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInFuture, ''), 'Failed asserting that user 1 successfully set a future expiration date for the test.txt share.' ); $row = $this->getShareByValidToken($token); @@ -561,11 +583,15 @@ class Test_Share extends PHPUnit_Framework_TestCase { 'Failed asserting that the returned row has an expiration date.' ); - // testGetShareByTokenExpirationExpired - $this->assertTrue( - OCP\Share::setExpirationDate('test', 'test.txt', $this->dateInPast), - 'Failed asserting that user 1 successfully set a past expiration date for the test.txt share.' - ); + // manipulate share table and set expire date to the past + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `item_type` = ? AND `item_source` = ? AND `uid_owner` = ? AND `share_type` = ?'); + $query->bindValue(1, new \DateTime($this->dateInPast), 'datetime'); + $query->bindValue(2, 'test'); + $query->bindValue(3, 'test.txt'); + $query->bindValue(4, $this->user1); + $query->bindValue(5, \OCP\Share::SHARE_TYPE_LINK); + $query->execute(); + $this->assertFalse( OCP\Share::getShareByToken($token), 'Failed asserting that an expired share could not be found.' -- cgit v1.2.3 From 8757a99f789614a9d05ec98a0e347f2f056b0710 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 14 Jul 2014 16:05:46 +0200 Subject: Fix enforced share expiration date to be based on share time --- core/js/js.js | 12 ++++ core/js/share.js | 28 ++++++-- core/js/tests/specs/coreSpec.js | 6 ++ core/js/tests/specs/shareSpec.js | 139 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 170 insertions(+), 15 deletions(-) (limited to 'core') diff --git a/core/js/js.js b/core/js/js.js index 4a9a5ce82ff..5c9d7bf0141 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1353,6 +1353,18 @@ OC.Util = { } }); }); + }, + + /** + * Remove the time component from a given date + * + * @param {Date} date date + * @return {Date} date with stripped time + */ + stripTime: function(date) { + // FIXME: likely to break when crossing DST + // would be better to use a library like momentJS + return new Date(date.getFullYear(), date.getMonth(), date.getDate()); } }; diff --git a/core/js/share.js b/core/js/share.js index e8d486055b0..14abdf18ade 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -436,7 +436,7 @@ OC.Share={ } } if (share.expiration != null) { - OC.Share.showExpirationDate(share.expiration); + OC.Share.showExpirationDate(share.expiration, share.stime); } }); } @@ -716,7 +716,24 @@ OC.Share={ dirname:function(path) { return path.replace(/\\/g,'/').replace(/\/[^\/]*$/, ''); }, - showExpirationDate:function(date) { + /** + * Displays the expiration date field + * + * @param {Date} date current expiration date + * @param {int} [shareTime] share timestamp in seconds, defaults to now + */ + showExpirationDate:function(date, shareTime) { + var now = new Date(); + var datePickerOptions = { + minDate: now, + maxDate: null + }; + if (_.isNumber(shareTime)) { + shareTime = new Date(shareTime * 1000); + } + if (!shareTime) { + shareTime = now; + } $('#expirationCheckbox').attr('checked', true); $('#expirationDate').val(date); $('#expirationDate').show('blind'); @@ -726,13 +743,14 @@ OC.Share={ }); if (oc_appconfig.core.defaultExpireDateEnforced) { $('#expirationCheckbox').attr('disabled', true); - $.datepicker.setDefaults({ - maxDate : new Date(date.replace(' 00:00:00', '')) - }); + shareTime = OC.Util.stripTime(shareTime).getTime(); + // max date is share date + X days + datePickerOptions.maxDate = new Date(shareTime + oc_appconfig.core.defaultExpireDate * 24 * 3600 * 1000); } if(oc_appconfig.core.defaultExpireDateEnabled) { $('#defaultExpireMessage').show('blind'); } + $.datepicker.setDefaults(datePickerOptions); } }; diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index dd9d4a79277..166210d0312 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -466,6 +466,12 @@ describe('Core base tests', function() { } }); }); + describe('stripTime', function() { + it('strips time from dates', function() { + expect(OC.Util.stripTime(new Date(2014, 2, 24, 15, 4, 45, 24))) + .toEqual(new Date(2014, 2, 24, 0, 0, 0, 0)); + }); + }); }); }); diff --git a/core/js/tests/specs/shareSpec.js b/core/js/tests/specs/shareSpec.js index 00a88ba36ef..32fecf82b65 100644 --- a/core/js/tests/specs/shareSpec.js +++ b/core/js/tests/specs/shareSpec.js @@ -83,16 +83,6 @@ describe('OC.Share tests', function() { expect($el.attr('data-item-source')).toEqual('123'); // TODO: expect that other parts are rendered correctly }); - it('shows default expiration date when set', function() { - oc_appconfig.core.defaultExpireDateEnabled = "yes"; - oc_appconfig.core.defaultExpireDate = ''; - // TODO: expect that default date was set - }); - it('shows default expiration date is set but disabled', function() { - oc_appconfig.core.defaultExpireDateEnabled = "no"; - oc_appconfig.core.defaultExpireDate = ''; - // TODO: expect that default date was NOT set - }); describe('Share with link', function() { // TODO: test ajax calls // TODO: test password field visibility (whenever enforced or not) @@ -265,6 +255,135 @@ describe('OC.Share tests', function() { OC.linkTo('', 'public.php')+'?service=files&t=anothertoken'; expect($('#dropdown #linkText').val()).toEqual(link); }); + describe('expiration date', function() { + var shareData; + var shareItem; + var clock; + + function showDropDown() { + OC.Share.showDropDown( + 'file', + 123, + $container, + 'http://localhost/dummylink', + 31, + 'folder' + ); + } + + beforeEach(function() { + // pick a fake date + clock = sinon.useFakeTimers(new Date(2014, 0, 20, 14, 0, 0).getTime()); + shareItem = { + displayname_owner: 'root', + expiration: null, + file_source: 123, + file_target: '/folder', + id: 20, + item_source: '123', + item_type: 'folder', + mail_send: '0', + parent: null, + path: '/folder', + permissions: OC.PERMISSION_READ, + share_type: OC.Share.SHARE_TYPE_LINK, + share_with: null, + stime: 1403884258, + storage: 1, + token: 'tehtoken', + uid_owner: 'root' + }; + shareData = { + reshare: [], + shares: [] + }; + loadItemStub.returns(shareData); + oc_appconfig.core.defaultExpireDate = 7; + oc_appconfig.core.defaultExpireDateEnabled = false; + oc_appconfig.core.defaultExpireDateEnforced = false; + }); + afterEach(function() { + clock.restore(); + }); + + it('does not check expiration date checkbox when no date was set', function() { + shareItem.expiration = null; + shareData.shares.push(shareItem); + showDropDown(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); + expect($('#dropdown #expirationDate').val()).toEqual(''); + }); + it('does not check expiration date checkbox for new share', function() { + showDropDown(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); + expect($('#dropdown #expirationDate').val()).toEqual(''); + }); + it('checks expiration date checkbox and populates field when expiration date was set', function() { + shareItem.expiration = 1234; + shareData.shares.push(shareItem); + showDropDown(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); + expect($('#dropdown #expirationDate').val()).toEqual('1234'); + }); + it('sets default date when default date setting is enabled', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + showDropDown(); + $('#dropdown [name=linkCheckbox]').click(); + // enabled by default + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); + // TODO: those zeros must go... + expect($('#dropdown #expirationDate').val()).toEqual('2014-1-27 00:00:00'); + + // disabling is allowed + $('#dropdown [name=expirationCheckbox]').click(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); + }); + it('enforces default date when enforced date setting is enabled', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + showDropDown(); + $('#dropdown [name=linkCheckbox]').click(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); + // TODO: those zeros must go... + expect($('#dropdown #expirationDate').val()).toEqual('2014-1-27 00:00:00'); + + // disabling is not allowed + expect($('#dropdown [name=expirationCheckbox]').prop('disabled')).toEqual(true); + $('#dropdown [name=expirationCheckbox]').click(); + expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); + }); + it('sets picker minDate to today and no maxDate by default', function() { + showDropDown(); + $('#dropdown [name=linkCheckbox]').click(); + $('#dropdown [name=expirationCheckbox]').click(); + expect($.datepicker._defaults.minDate).toEqual(new Date()); + expect($.datepicker._defaults.maxDate).toEqual(null); + }); + it('limits the date range to X days after share time when enforced', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + showDropDown(); + $('#dropdown [name=linkCheckbox]').click(); + expect($.datepicker._defaults.minDate).toEqual(new Date()); + expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); + }); + it('limits the date range to X days after share time when enforced, even when redisplayed the next days', function() { + // item exists, was created two days ago + shareItem.expiration = '2014-1-27'; + // share time has time component but must be stripped later + shareItem.stime = new Date(2014, 0, 20, 11, 0, 25).getTime() / 1000; + shareData.shares.push(shareItem); + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + showDropDown(); + expect($.datepicker._defaults.minDate).toEqual(new Date()); + expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); + }); + }); }); describe('"sharesChanged" event', function() { var autocompleteOptions; -- cgit v1.2.3 From 1cd1214b9389a3fad3f13852a4436646a85df77b Mon Sep 17 00:00:00 2001 From: Michael Göhler Date: Sat, 26 Jul 2014 13:06:51 +0200 Subject: max icon size for app menu --- core/css/header.css | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core') diff --git a/core/css/header.css b/core/css/header.css index 86db48a3f08..2df8cdd3aa3 100644 --- a/core/css/header.css +++ b/core/css/header.css @@ -190,6 +190,8 @@ #navigation .app-icon { margin: 0 auto; padding: 0; + max-height: 32px; + max-width: 32px; } /* Apps management */ -- cgit v1.2.3 From 64094c5384d1731eaf819937ed412b9d7511a130 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Tue, 29 Jul 2014 14:53:43 +0200 Subject: use more understandable 'link' icon for public links (instead of hard to recognize globe), fix #9707 --- core/img/actions/public.png | Bin 338 -> 307 bytes core/img/actions/public.svg | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/img/actions/public.png b/core/img/actions/public.png index 077bb7504de..772838ad205 100644 Binary files a/core/img/actions/public.png and b/core/img/actions/public.png differ diff --git a/core/img/actions/public.svg b/core/img/actions/public.svg index c70a7627788..99a71c6cb5b 100644 --- a/core/img/actions/public.svg +++ b/core/img/actions/public.svg @@ -1,4 +1,7 @@ - - + + + + + -- cgit v1.2.3 From 8f9deb118aabcd9dc94bb99cbeec56199a7cdd29 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Wed, 30 Jul 2014 11:07:16 +0200 Subject: also use link icon for the folders .. --- core/img/filetypes/folder-public.png | Bin 1308 -> 1251 bytes core/img/filetypes/folder-public.svg | 41 +++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 19 deletions(-) (limited to 'core') diff --git a/core/img/filetypes/folder-public.png b/core/img/filetypes/folder-public.png index 40d8cd067bb..7f8f8e3411c 100644 Binary files a/core/img/filetypes/folder-public.png and b/core/img/filetypes/folder-public.png differ diff --git a/core/img/filetypes/folder-public.svg b/core/img/filetypes/folder-public.svg index f1f9321fd35..9516a7de59d 100644 --- a/core/img/filetypes/folder-public.svg +++ b/core/img/filetypes/folder-public.svg @@ -1,59 +1,62 @@ - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - + + + + -- cgit v1.2.3 From 4f40cde66afe2376ede177020882e5236a5a3373 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 29 Jul 2014 17:23:44 +0200 Subject: Also keep maxY into account when scaling a preview while preserving aspect ratio --- apps/files_sharing/ajax/publicpreview.php | 4 ---- core/ajax/preview.php | 4 ---- lib/private/preview.php | 10 ++++++++-- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'core') diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index 0b2af7a6e59..f5343a7ef26 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -70,10 +70,6 @@ if(substr($path, 0, 1) === '/') { $path = substr($path, 1); } -if ($keepAspect === true) { - $maxY = $maxX; -} - if($maxX === 0 || $maxY === 0) { \OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST); \OC_Log::write('core-preview', 'x and/or y set to 0', \OC_Log::DEBUG); diff --git a/core/ajax/preview.php b/core/ajax/preview.php index d38043707ac..edbd41d2db4 100644 --- a/core/ajax/preview.php +++ b/core/ajax/preview.php @@ -21,10 +21,6 @@ if ($file === '') { exit; } -if ($keepAspect === true) { - $maxY = $maxX; -} - if ($maxX === 0 || $maxY === 0) { //400 Bad Request \OC_Response::setStatus(400); diff --git a/lib/private/preview.php b/lib/private/preview.php index 8089379bde5..6172519c7d1 100755 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -561,9 +561,15 @@ class Preview { $realX = (int)$image->width(); $realY = (int)$image->height(); - // compute $maxY using the aspect of the generated preview + // compute $maxY and $maxX using the aspect of the generated preview if ($this->keepAspect) { - $y = $x / ($realX / $realY); + $ratio = $realX / $realY; + if($x / $ratio < $y) { + // width restricted + $y = $x / $ratio; + } else { + $x = $y * $ratio; + } } if ($x === $realX && $y === $realY) { -- cgit v1.2.3 From 57c954a345a21b0e9b2815b9ae015888ce66acbd Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Wed, 30 Jul 2014 18:00:46 +0200 Subject: fix notification preventing top bar clickability, fix #9680 --- core/css/styles.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/css/styles.css b/core/css/styles.css index 17ed3fbc74c..4ac43f439b4 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -680,7 +680,13 @@ label.infield { .center { text-align:center; } .inlineblock { display: inline-block; } -#notification-container { position: fixed; top: 0px; width: 100%; text-align: center; z-index: 101; line-height: 1.2;} +#notification-container { + position: absolute; + top: 0; + width: 100%; + text-align: center; + line-height: 1.2; +} #notification, #update-notification { z-index: 101; background-color: #fc4; -- cgit v1.2.3 From 32cec6cae43ff0d72632657749c789d4c4d36279 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Wed, 30 Jul 2014 18:02:53 +0200 Subject: fix yellow notification style --- core/css/styles.css | 13 ++++++++++--- core/js/js.js | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/css/styles.css b/core/css/styles.css index 4ac43f439b4..066126b41eb 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -685,20 +685,27 @@ label.infield { top: 0; width: 100%; text-align: center; - line-height: 1.2; } #notification, #update-notification { + margin: 0 auto; z-index: 101; background-color: #fc4; border: 0; - padding: 0 .7em .3em; + padding: 1px 8px; display: none; position: relative; top: 0; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=90)"; + filter:alpha(opacity=90); + opacity: .9; +} +#notification span, #update-notification span { + cursor: pointer; + font-weight: bold; + margin-left: 1em; } -#notification span, #update-notification span { cursor:pointer; font-weight:bold; margin-left:1em; } tr .action:not(.permanent), .selectedActions a { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; } tr:hover .action, tr .action.permanent, .selectedActions a { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter:alpha(opacity=50); opacity:.5; } diff --git a/core/js/js.js b/core/js/js.js index 5c9d7bf0141..60f9cc11a58 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -696,7 +696,7 @@ OC.Notification={ var notification = $('#notification'); if((notification.filter('span.undo').length == 1) || OC.Notification.isHidden()){ notification.html(html); - notification.fadeIn().css("display","inline"); + notification.fadeIn().css('display','inline-block'); }else{ OC.Notification.queuedNotifications.push(html); } @@ -710,7 +710,7 @@ OC.Notification={ var notification = $('#notification'); if((notification.filter('span.undo').length == 1) || OC.Notification.isHidden()){ notification.text(text); - notification.fadeIn().css("display","inline"); + notification.fadeIn().css('display','inline-block'); }else{ OC.Notification.queuedNotifications.push($('
').text(text).html()); } -- cgit v1.2.3 From a0f024fec22854509de19a1aa735a1567c3b534c Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Wed, 30 Jul 2014 18:16:32 +0200 Subject: set max width for notifications so they won't overlap the whole header --- core/css/styles.css | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/css/styles.css b/core/css/styles.css index 066126b41eb..3390b3000e2 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -688,6 +688,7 @@ label.infield { } #notification, #update-notification { margin: 0 auto; + max-width: 60%; z-index: 101; background-color: #fc4; border: 0; -- cgit v1.2.3