diff options
30 files changed, 613 insertions, 158 deletions
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index 4c426dd1052..30eeaaacf63 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -343,6 +343,9 @@ class FilesPlugin extends ServerPlugin { $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) { return $node->getSize(); }); + $propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) { + return $node->getFileInfo()->getMountPoint()->getMountType(); + }); } if ($node instanceof \OCA\DAV\Connector\Sabre\Node) { @@ -383,10 +386,6 @@ class FilesPlugin extends ServerPlugin { return $node->getSize(); }); } - - $propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) { - return $node->getFileInfo()->getMountPoint()->getMountType(); - }); } /** diff --git a/apps/theming/css/settings-admin.css b/apps/theming/css/settings-admin.css index 8cc3f0dfe14..e401d77e4b6 100644 --- a/apps/theming/css/settings-admin.css +++ b/apps/theming/css/settings-admin.css @@ -26,10 +26,20 @@ display: inline-block; visibility: hidden; } -#theming form .theme-undo { +form.uploadButton { + width: 356px; +} +#theming form .theme-undo, +#theming .theme-remove-bg { + cursor: pointer; + opacity: .3; + padding: 7px; + vertical-align: top; + display: inline-block; + float: right; position: relative; top: 4px; - left: 158px; + right: 0px; visibility: visible; } #theming input[type='text']:focus + .theme-undo, @@ -54,7 +64,8 @@ margin: 2px 0px; } -#theming .icon-upload { +#theming .icon-upload, +#theming .icon-loading-small { padding: 8px 20px; width: 20px; margin: 2px 0px; diff --git a/apps/theming/css/theming.scss b/apps/theming/css/theming.scss index 71e0df6735e..2a5a0e5cd46 100644 --- a/apps/theming/css/theming.scss +++ b/apps/theming/css/theming.scss @@ -64,4 +64,50 @@ input.primary { #body-login input.login { background-image: url('../../../core/img/actions/confirm.svg'); } +} + +// plain background color for login page +@if $image-login-plain == 'true' { + #body-login, #firstrunwizard .firstrunwizard-header, #theming-preview { + background-image: none !important; + background-color: $color-primary; + } + #body-login { + + a, label, p { + color: $color-primary-text !important; + } + + @if (lightness($color-primary) > 50) { + #submit { + border-color: nc-darken($color-primary, 20%); + background-color: nc-darken($color-primary, 20%); + } + #submit:hover { + border-color: nc-darken($color-primary, 10%); + background-color: nc-darken($color-primary, 10%); + } + input[type='checkbox'].checkbox--white + label:before { + border-color: nc-darken($color-primary, 40%) !important; + } + input[type='checkbox'].checkbox--white:not(:disabled):not(:checked) + label:hover:before, + input[type='checkbox'].checkbox--white:focus + label:before { + border-color: nc-darken($color-primary, 30%) !important; + } + input[type='checkbox'].checkbox--white:checked + label:before { + border-color: nc-darken($color-primary, 30%) !important; + background-image: url('../../../core/img/actions/checkbox-mark.svg'); + background-color: nc-darken($color-primary, 30%) !important; + } + } @else { + #submit { + border-color: nc-lighten($color-primary, 20%); + background-color: nc-lighten($color-primary, 20%); + } + #submit:hover { + border-color: nc-lighten($color-primary, 10%); + background-color: nc-lighten($color-primary, 10%); + } + } + } }
\ No newline at end of file diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 802f6e05c07..5d91892c007 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -35,6 +35,7 @@ function setThemingValue(setting, value) { OC.msg.finishedSaving('#theming_settings_msg', response); $('#theming_settings_loading').hide(); }); + } function preview(setting, value) { @@ -74,18 +75,13 @@ function preview(setting, value) { previewImageLogo.src = OC.getRootPath() + '/core/img/logo-icon.svg?v' + timestamp; } } - if (setting === 'backgroundMime') { - var previewImage = document.getElementById('theming-preview'); - if (value !== '') { - previewImage.style.backgroundImage = "url('" + OC.generateUrl('/apps/theming/loginbackground') + "?v" + timestamp + "')"; - } else { - previewImage.style.backgroundImage = "url('" + OC.getRootPath() + '/core/img/background.jpg?v' + timestamp + "')"; - } - } if (setting === 'name') { window.document.title = t('core', 'Admin') + " - " + value; } + + hideUndoButton(setting, value); + } function hideUndoButton(setting, value) { @@ -103,6 +99,14 @@ function hideUndoButton(setting, value) { } else { $('.theme-undo[data-setting=' + setting + ']').show(); } + + if(setting === 'backgroundMime' && value !== 'backgroundColor') { + $('.theme-remove-bg').show(); + } + if(setting === 'backgroundMime' && value === 'backgroundColor') { + $('.theme-remove-bg').hide(); + $('.theme-undo[data-setting=backgroundMime]').show(); + } } $(document).ready(function () { @@ -116,6 +120,7 @@ $(document).ready(function () { } hideUndoButton(setting, value); }); + var uploadParamsLogo = { pasteZone: null, dropZone: null, @@ -208,4 +213,16 @@ $(document).ready(function () { preview(setting, response.data.value); }); }); + + $('.theme-remove-bg').click(function() { + startLoading(); + $.post( + OC.generateUrl('/apps/theming/ajax/updateLogo'), {'backgroundColor' : true} + ).done(function(response) { + preview('backgroundMime', 'backgroundColor'); + }).fail(function(response) { + OC.msg.finishedSaving('#theming_settings_msg', response); + }); + }); + }); diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index faaff1f2174..225673079a3 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -185,6 +185,20 @@ class ThemingController extends Controller { * @return DataResponse */ public function updateLogo() { + $backgroundColor = $this->request->getParam('backgroundColor', false); + if($backgroundColor) { + $this->themingDefaults->set('backgroundMime', 'backgroundColor'); + return new DataResponse( + [ + 'data' => + [ + 'name' => 'backgroundColor', + 'message' => $this->l10n->t('Saved') + ], + 'status' => 'success' + ] + ); + } $newLogo = $this->request->getUploadedFile('uploadlogo'); $newBackgroundLogo = $this->request->getUploadedFile('upload-login-background'); if (empty($newLogo) && empty($newBackgroundLogo)) { diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php index 39547af4916..0824a36ccdc 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -129,9 +129,10 @@ class ThemingDefaults extends \OC_Defaults { /** * Themed logo url * + * @param bool $useSvg Whether to point to the SVG image or a fallback * @return string */ - public function getLogo() { + public function getLogo($useSvg = true) { $logo = $this->config->getAppValue('theming', 'logoMime', false); $logoExists = true; @@ -144,7 +145,12 @@ class ThemingDefaults extends \OC_Defaults { $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0'); if(!$logo || !$logoExists) { - return $this->urlGenerator->imagePath('core','logo.svg') . '?v=' . $cacheBusterCounter; + if($useSvg) { + $logo = $this->urlGenerator->imagePath('core', 'logo.svg'); + } else { + $logo = $this->urlGenerator->imagePath('core', 'logo.png'); + } + return $logo . '?v=' . $cacheBusterCounter; } return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter; @@ -190,6 +196,7 @@ class ThemingDefaults extends \OC_Defaults { $variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'"; $variables['image-login-background'] = "'".$this->urlGenerator->getAbsoluteURL($this->getBackground())."'"; + $variables['image-login-plain'] = 'false'; if ($this->config->getAppValue('theming', 'color', null) !== null) { if ($this->util->invertTextColor($this->getColorPrimary())) { @@ -200,6 +207,10 @@ class ThemingDefaults extends \OC_Defaults { $variables['color-primary'] = $this->getColorPrimary(); $variables['color-primary-text'] = $colorPrimaryText; } + + if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') { + $variables['image-login-plain'] = 'true'; + } $cache->set('getScssVariables', $variables); return $variables; } diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 858329eca48..858b916c932 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -67,7 +67,7 @@ style('theming', 'settings-admin'); </label> </div> <div> - <form class="uploadButton inlineblock" method="post" action="<?php p($_['uploadLogoRoute']) ?>"> + <form class="uploadButton" method="post" action="<?php p($_['uploadLogoRoute']) ?>"> <input type="hidden" id="current-logoMime" name="current-logoMime" value="<?php p($_['logoMime']); ?>" /> <label for="uploadlogo"><span><?php p($l->t('Logo')) ?></span></label> <input id="uploadlogo" class="upload-logo-field" name="uploadlogo" type="file" /> @@ -76,16 +76,16 @@ style('theming', 'settings-admin'); </form> </div> <div> - <form class="uploadButton inlineblock" method="post" action="<?php p($_['uploadLogoRoute']) ?>"> + <form class="uploadButton" method="post" action="<?php p($_['uploadLogoRoute']) ?>"> <input type="hidden" id="current-backgroundMime" name="current-backgroundMime" value="<?php p($_['backgroundMime']); ?>" /> <label for="upload-login-background"><span><?php p($l->t('Login image')) ?></span></label> <input id="upload-login-background" class="upload-logo-field" name="upload-login-background" type="file"> <label for="upload-login-background" class="button icon-upload svg" id="upload-login-background" title="<?php p($l->t("Upload new login background")) ?>"></label> <div data-setting="backgroundMime" data-toggle="tooltip" data-original-title="<?php p($l->t('reset to default')); ?>" class="theme-undo icon icon-history"></div> + <div class="theme-remove-bg icon icon-delete" data-toggle="tooltip" data-original-title="<?php p($l->t('Remove background image')); ?>"></div> </form> </div> - - <div id="theming-preview" style="background-color:<?php p($_['color']);?>; background-image:url(<?php p($_['background']); ?>);"> + <div id="theming-preview"> <img src="<?php p($_['logo']); ?>" id="theming-preview-logo" /> </div> <?php } ?> diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php index f22c317d73d..cbdb86d0358 100644 --- a/apps/theming/tests/Controller/ThemingControllerTest.php +++ b/apps/theming/tests/Controller/ThemingControllerTest.php @@ -152,11 +152,16 @@ class ThemingControllerTest extends TestCase { public function testUpdateLogoNoData() { $this->request ->expects($this->at(0)) + ->method('getParam') + ->with('backgroundColor') + ->willReturn(false); + $this->request + ->expects($this->at(1)) ->method('getUploadedFile') ->with('uploadlogo') ->willReturn(null); $this->request - ->expects($this->at(1)) + ->expects($this->at(2)) ->method('getUploadedFile') ->with('upload-login-background') ->willReturn(null); @@ -179,6 +184,29 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->updateLogo()); } + public function testUpdateBackgroundColor() { + $this->request + ->expects($this->at(0)) + ->method('getParam') + ->with('backgroundColor') + ->willReturn(true); + $this->themingDefaults + ->expects($this->once()) + ->method('set') + ->with('backgroundMime', 'backgroundColor'); + $expected = new DataResponse( + [ + 'data' => + [ + 'name' => 'backgroundColor', + 'message' => $this->l10n->t('Saved') + ], + 'status' => 'success' + ] + ); + $this->assertEquals($expected, $this->themingController->updateLogo()); + } + public function dataUpdateImages() { return [ [false], @@ -194,6 +222,11 @@ class ThemingControllerTest extends TestCase { touch($tmpLogo); $this->request ->expects($this->at(0)) + ->method('getParam') + ->with('backgroundColor') + ->willReturn(false); + $this->request + ->expects($this->at(1)) ->method('getUploadedFile') ->with('uploadlogo') ->willReturn([ @@ -202,7 +235,7 @@ class ThemingControllerTest extends TestCase { 'name' => 'logo.svg', ]); $this->request - ->expects($this->at(1)) + ->expects($this->at(2)) ->method('getUploadedFile') ->with('upload-login-background') ->willReturn(null); @@ -259,11 +292,16 @@ class ThemingControllerTest extends TestCase { file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/desktopapp.png')); $this->request ->expects($this->at(0)) + ->method('getParam') + ->with('backgroundColor') + ->willReturn(false); + $this->request + ->expects($this->at(1)) ->method('getUploadedFile') ->with('uploadlogo') ->willReturn(null); $this->request - ->expects($this->at(1)) + ->expects($this->at(2)) ->method('getUploadedFile') ->with('upload-login-background') ->willReturn([ @@ -322,11 +360,16 @@ class ThemingControllerTest extends TestCase { file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/data.zip')); $this->request ->expects($this->at(0)) + ->method('getParam') + ->with('backgroundColor') + ->willReturn(false); + $this->request + ->expects($this->at(1)) ->method('getUploadedFile') ->with('uploadlogo') ->willReturn(null); $this->request - ->expects($this->at(1)) + ->expects($this->at(2)) ->method('getUploadedFile') ->with('upload-login-background') ->willReturn([ diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index 7535eddb4f0..a7cb7790aa6 100644 --- a/apps/theming/tests/ThemingDefaultsTest.php +++ b/apps/theming/tests/ThemingDefaultsTest.php @@ -431,7 +431,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('custom-background?v=0', $this->template->getBackground()); } - public function testGetLogoDefault() { + private function getLogoHelper($withName, $useSvg) { $this->appData->expects($this->once()) ->method('getFolder') ->willThrowException(new NotFoundException()); @@ -452,9 +452,17 @@ class ThemingDefaultsTest extends TestCase { ->willThrowException(new \Exception()); $this->urlGenerator->expects($this->once()) ->method('imagePath') - ->with('core', 'logo.svg') + ->with('core', $withName) ->willReturn('core-logo'); - $this->assertEquals('core-logo?v=0', $this->template->getLogo()); + $this->assertEquals('core-logo?v=0', $this->template->getLogo($useSvg)); + } + + public function testGetLogoDefaultWithSvg() { + $this->getLogoHelper('logo.svg', true); + } + + public function testGetLogoDefaultWithoutSvg() { + $this->getLogoHelper('logo.png', false); } public function testGetLogoCustom() { @@ -525,7 +533,8 @@ class ThemingDefaultsTest extends TestCase { 'image-logo' => "'absolute-custom-logo?v=0'", 'image-login-background' => "'absolute-custom-background?v=0'", 'color-primary' => $this->defaults->getColorPrimary(), - 'color-primary-text' => '#ffffff' + 'color-primary-text' => '#ffffff', + 'image-login-plain' => 'false' ]; $this->assertEquals($expected, $this->template->getScssVariables()); diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index cbdcafc58d6..70e505c18af 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -29,46 +29,26 @@ $helper = new \OCA\User_LDAP\Helper(\OC::$server->getConfig()); $configPrefixes = $helper->getServerConfigurationPrefixes(true); -$ldapWrapper = new OCA\User_LDAP\LDAP(); -$ocConfig = \OC::$server->getConfig(); -$notificationManager = \OC::$server->getNotificationManager(); -$notificationManager->registerNotifier(function() { - return new \OCA\User_LDAP\Notification\Notifier( - \OC::$server->getL10NFactory() - ); -}, function() { +if(count($configPrefixes) > 0) { + $ldapWrapper = new OCA\User_LDAP\LDAP(); + $ocConfig = \OC::$server->getConfig(); + $notificationManager = \OC::$server->getNotificationManager(); + $notificationManager->registerNotifier(function() { + return new \OCA\User_LDAP\Notification\Notifier( + \OC::$server->getL10NFactory() + ); + }, function() { $l = \OC::$server->getL10N('user_ldap'); return [ 'id' => 'user_ldap', 'name' => $l->t('LDAP user and group backend'), ]; -}); -if(count($configPrefixes) === 1) { - $dbc = \OC::$server->getDatabaseConnection(); - $userManager = new OCA\User_LDAP\User\Manager($ocConfig, - new OCA\User_LDAP\FilesystemHelper(), - new OCA\User_LDAP\LogWrapper(), - \OC::$server->getAvatarManager(), - new \OCP\Image(), - $dbc, - \OC::$server->getUserManager(), - $notificationManager - ); - $connector = new OCA\User_LDAP\Connection($ldapWrapper, $configPrefixes[0]); - $ldapAccess = new OCA\User_LDAP\Access($connector, $ldapWrapper, $userManager, $helper); + }); - $ldapAccess->setUserMapper(new OCA\User_LDAP\Mapping\UserMapping($dbc)); - $ldapAccess->setGroupMapper(new OCA\User_LDAP\Mapping\GroupMapping($dbc)); - $userBackend = new OCA\User_LDAP\User_LDAP($ldapAccess, $ocConfig, $notificationManager); - $groupBackend = new \OCA\User_LDAP\Group_LDAP($ldapAccess); -} else if(count($configPrefixes) > 1) { $userBackend = new OCA\User_LDAP\User_Proxy( $configPrefixes, $ldapWrapper, $ocConfig, $notificationManager ); $groupBackend = new OCA\User_LDAP\Group_Proxy($configPrefixes, $ldapWrapper); -} - -if(count($configPrefixes) > 0) { // register user backend OC_User::useBackend($userBackend); \OC::$server->getGroupManager()->addBackend($groupBackend); diff --git a/config/config.sample.php b/config/config.sample.php index d106d03f602..9f2ede88169 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1235,16 +1235,23 @@ $CONFIG = array( 'sqlite.journal_mode' => 'DELETE', /** - * If this setting is set to true MySQL can handle 4 byte characters instead of - * 3 byte characters - * + * During setup, if requirements are met (see below), this setting is set to true + * and MySQL can handle 4 byte characters instead of 3 byte characters. + * + * If you want to convert an existing 3-byte setup into a 4-byte setup please + * set the parameters in MySQL as mentioned below and run the migration command: + * ./occ db:convert-mysql-charset + * The config setting will be set automatically after a successful run. + * + * Consult the documentation for more details. + * * MySQL requires a special setup for longer indexes (> 767 bytes) which are * needed: * * [mysqld] - * innodb_large_prefix=true - * innodb_file_format=barracuda - * innodb_file_per_table=true + * innodb_large_prefix=ON + * innodb_file_format=Barracuda + * innodb_file_per_table=ON * * Tables will be created with * * character set: utf8mb4 @@ -1257,8 +1264,6 @@ $CONFIG = array( * https://mariadb.com/kb/en/mariadb/xtradbinnodb-server-system-variables/#innodb_large_prefix * http://www.tocker.ca/2013/10/31/benchmarking-innodb-page-compression-performance.html * http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/ - * - * WARNING: EXPERIMENTAL */ 'mysql.utf8mb4' => false, diff --git a/core/Command/Db/ConvertMysqlToMB4.php b/core/Command/Db/ConvertMysqlToMB4.php index 286274753ee..38aff8b09d8 100644 --- a/core/Command/Db/ConvertMysqlToMB4.php +++ b/core/Command/Db/ConvertMysqlToMB4.php @@ -22,6 +22,7 @@ namespace OC\Core\Command\Db; use Doctrine\DBAL\Platforms\MySqlPlatform; +use OC\DB\MySqlTools; use OC\Migration\ConsoleOutput; use OC\Repair\Collation; use OCP\IConfig; @@ -71,18 +72,17 @@ class ConvertMysqlToMB4 extends Command { return 1; } - $oldValue = $this->config->getSystemValue('mysql.utf8mb4', false); - // enable charset - $this->config->setSystemValue('mysql.utf8mb4', true); - - if (!$this->connection->supports4ByteText()) { + $tools = new MySqlTools(); + if (!$tools->supports4ByteCharset($this->connection)) { $url = $this->urlGenerator->linkToDocs('admin-mysql-utf8mb4'); $output->writeln("The database is not properly setup to use the charset utf8mb4."); $output->writeln("For more information please read the documentation at $url"); - $this->config->setSystemValue('mysql.utf8mb4', $oldValue); return 1; } + // enable charset + $this->config->setSystemValue('mysql.utf8mb4', true); + // run conversion $coll = new Collation($this->config, $this->logger, $this->connection, false); $coll->run(new ConsoleOutput($output)); diff --git a/core/css/guest.css b/core/css/guest.css index be8b2a604c7..689eb45d65f 100644 --- a/core/css/guest.css +++ b/core/css/guest.css @@ -70,9 +70,16 @@ h3 { background-size: 175px; background-position: center; width: 252px; - height: 120px; + min-height: 120px; + max-height: 200px; margin: 0 auto; } + +#header .logo img { + opacity: 0; + max-width: 100%; + max-height: 200px; +} .wrapper { min-height: 100%; margin: 0 auto -70px; diff --git a/core/shipped.json b/core/shipped.json index e114ec769e7..d064cbb5c37 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -5,7 +5,6 @@ "comments", "dav", "encryption", - "external", "federatedfilesharing", "federation", "files", diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php index 1e2559d6960..2c2373d53aa 100644 --- a/core/templates/layout.guest.php +++ b/core/templates/layout.guest.php @@ -40,6 +40,10 @@ <h1 class="hidden-visually"> <?php p($theme->getName()); ?> </h1> + <?php if(\OC::$server->getConfig()->getSystemValue('installed', false) + && \OC::$server->getConfig()->getAppValue('theming', 'logoMime', false)): ?> + <img src="<?php p($theme->getLogo()); ?>"/> + <?php endif; ?> </div> <div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div> </div> diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 2151aeff33b..703d624397c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -488,6 +488,7 @@ return array( 'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php', 'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php', 'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php', + 'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php', 'OC\\DB\\NoCheckMigrator' => $baseDir . '/lib/private/DB/NoCheckMigrator.php', 'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php', 'OC\\DB\\OracleConnection' => $baseDir . '/lib/private/DB/OracleConnection.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ec5190bc71d..ff7118e5bb1 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -518,6 +518,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php', 'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php', 'OC\\DB\\MySQLMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/MySQLMigrator.php', + 'OC\\DB\\MySqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/MySqlTools.php', 'OC\\DB\\NoCheckMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/NoCheckMigrator.php', 'OC\\DB\\OCSqlitePlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCSqlitePlatform.php', 'OC\\DB\\OracleConnection' => __DIR__ . '/../../..' . '/lib/private/DB/OracleConnection.php', diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php new file mode 100644 index 00000000000..32f1de887c3 --- /dev/null +++ b/lib/private/DB/MySqlTools.php @@ -0,0 +1,49 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\DB; + +use OCP\IDBConnection; + +/** +* Various MySQL specific helper functions. +*/ +class MySqlTools { + + /** + * @param Connection $connection + * @return bool + */ + public function supports4ByteCharset(IDBConnection $connection) { + foreach (['innodb_file_format' => 'Barracuda', 'innodb_large_prefix' => 'ON', 'innodb_file_per_table' => 'ON'] as $var => $val) { + $result = $connection->executeQuery("SHOW VARIABLES LIKE '$var'"); + $rows = $result->fetch(); + $result->closeCursor(); + if ($rows === false) { + return false; + } + if (strcasecmp($rows['Value'], $val) !== 0) { + return false; + } + } + return true; + } +} diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 3442e8e9430..0ae79345e4c 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -357,7 +357,7 @@ EOF; } $this->headerAdded = true; - $logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo()); + $logoUrl = $this->urlGenerator->getAbsoluteURL($this->themingDefaults->getLogo(false)); $this->htmlBody .= vsprintf($this->header, [$this->themingDefaults->getColorPrimary(), $logoUrl, $this->themingDefaults->getName()]); } diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php index 9998ca401d9..8290d675500 100644 --- a/lib/private/Setup/MySQL.php +++ b/lib/private/Setup/MySQL.php @@ -27,6 +27,7 @@ */ namespace OC\Setup; +use OC\DB\MySqlTools; use OCP\IDBConnection; class MySQL extends AbstractDatabase { @@ -36,6 +37,13 @@ class MySQL extends AbstractDatabase { //check if the database user has admin right $connection = $this->connect(['dbname' => null]); + // detect mb4 + $tools = new MySqlTools(); + if ($tools->supports4ByteCharset($connection)) { + $this->config->setValue('mysql.utf8mb4', true); + $connection = $this->connect(); + } + $this->createSpecificUser($username, $connection); //create the database diff --git a/lib/private/legacy/defaults.php b/lib/private/legacy/defaults.php index cc4991efd3e..f6d72d9776d 100644 --- a/lib/private/legacy/defaults.php +++ b/lib/private/legacy/defaults.php @@ -47,9 +47,8 @@ class OC_Defaults { private $defaultSlogan; private $defaultLogoClaim; private $defaultColorPrimary; - private $defaultLogoUrl; - function __construct() { + public function __construct() { $this->l = \OC::$server->getL10N('lib'); $this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */ @@ -65,8 +64,6 @@ class OC_Defaults { $this->defaultSlogan = $this->l->t('a safe home for all your data'); $this->defaultLogoClaim = ''; $this->defaultColorPrimary = '#0082c9'; - $this->defaultLogoUrl = \OC::$server->getURLGenerator()->imagePath('core','logo.svg'); - $this->defaultLogoUrl .= '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion())); $themePath = OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php'; if (file_exists($themePath)) { @@ -307,13 +304,19 @@ class OC_Defaults { /** * Themed logo url * + * @param bool $useSvg Whether to point to the SVG image or a fallback * @return string */ - public function getLogo() { + public function getLogo($useSvg = true) { if ($this->themeExist('getLogo')) { - return $this->theme->getLogo(); + return $this->theme->getLogo($useSvg); } - return $this->defaultLogoUrl; + if($useSvg) { + $logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.svg'); + } else { + $logo = \OC::$server->getURLGenerator()->imagePath('core', 'logo.png'); + } + return $logo . '?v=' . hash('sha1', implode('.', \OCP\Util::getVersion())); } } diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php index 9a919ff12f2..b4c69327438 100644 --- a/lib/private/legacy/template.php +++ b/lib/private/legacy/template.php @@ -292,6 +292,11 @@ class OC_Template extends \OC\Template\Base { * @param string $hint An optional hint message - needs to be properly escaped */ public static function printErrorPage( $error_msg, $hint = '' ) { + if (\OC_App::isEnabled('theming') && !\OC_App::isAppLoaded('theming')) { + \OC_App::loadApp('theming'); + } + + if ($error_msg === $hint) { // If the hint is the same as the message there is no need to display it twice. $hint = ''; diff --git a/lib/public/Defaults.php b/lib/public/Defaults.php index dbde78bce68..543657694c5 100644 --- a/lib/public/Defaults.php +++ b/lib/public/Defaults.php @@ -178,11 +178,12 @@ class Defaults { /** * Themed logo url * + * @param bool $useSvg Whether to point to the SVG image or a fallback * @return string * @since 12.0.0 */ - public function getLogo() { - return $this->defaults->getLogo(); + public function getLogo($useSvg = true) { + return $this->defaults->getLogo($useSvg); } /** diff --git a/lib/public/Security/ISecureRandom.php b/lib/public/Security/ISecureRandom.php index c60529ef803..14190639f44 100644 --- a/lib/public/Security/ISecureRandom.php +++ b/lib/public/Security/ISecureRandom.php @@ -45,6 +45,13 @@ interface ISecureRandom { const CHAR_SYMBOLS = '!\"#$%&\\\'()* +,-./:;<=>?@[\]^_`{|}~'; /** + * Characters that can be used for <code>generate($length, $characters)</code>, to + * generate human readable random strings. Lower- and upper-case characters and digits + * are included. Characters which are ambiguous are excluded, such as I, l, and 1 and so on. + */ + const CHAR_HUMAN_READABLE = "abcdefgijkmnopqrstwxyzABCDEFGHJKLMNPQRSTWXYZ23456789"; + + /** * Convenience method to get a low strength random number generator. * * Low Strength should be used anywhere that random strings are needed diff --git a/settings/BackgroundJobs/VerifyUserData.php b/settings/BackgroundJobs/VerifyUserData.php index 4a32398f6c4..8c02ae1727c 100644 --- a/settings/BackgroundJobs/VerifyUserData.php +++ b/settings/BackgroundJobs/VerifyUserData.php @@ -96,6 +96,8 @@ class VerifyUserData extends Job { $jobList->remove($this, $this->argument); if ($this->retainJob) { $this->reAddJob($jobList, $this->argument); + } else { + $this->resetVerificationState(); } } @@ -270,4 +272,17 @@ class VerifyUserData extends Job { return ((time() - $lastRun) > $this->interval); } + + /** + * reset verification state after max tries are reached + */ + protected function resetVerificationState() { + $user = $this->userManager->get($this->argument['uid']); + if ($user !== null) { + $accountData = $this->accountManager->getUser($user); + $accountData[$this->argument['type']]['verified'] = AccountManager::NOT_VERIFIED; + $this->accountManager->updateUser($user, $accountData); + } + } + } diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php index 57192e119a9..7bb8a6654e6 100644 --- a/settings/Controller/AuthSettingsController.php +++ b/settings/Controller/AuthSettingsController.php @@ -154,16 +154,16 @@ class AuthSettingsController extends Controller { } /** - * Return a 20 digit device password + * Return a 25 digit device password * - * Example: ABCDE-FGHIJ-KLMNO-PQRST + * Example: AbCdE-fGhIj-KlMnO-pQrSt-12345 * * @return string */ private function generateRandomDeviceToken() { $groups = []; - for ($i = 0; $i < 4; $i++) { - $groups[] = $this->random->generate(5, implode('', range('A', 'Z'))); + for ($i = 0; $i < 5; $i++) { + $groups[] = $this->random->generate(5, ISecureRandom::CHAR_HUMAN_READABLE); } return implode('-', $groups); } diff --git a/settings/css/settings.css b/settings/css/settings.css index 0777f7e4cf4..fb71e5ece23 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -2,8 +2,13 @@ This file is licensed under the Affero General Public License version 3 or later. See the COPYING-README file. */ -select#languageinput, select#timezone { width:15em; } -input#openid, input#webdav { width:20em; } +select#languageinput, select#timezone { + width: 15em; +} + +input#openid, input#webdav { + width: 20em; +} /* PERSONAL */ @@ -11,21 +16,27 @@ input#openid, input#webdav { width:20em; } .nav-icon-personal-settings { background-image: url('../img/personal.svg?v=1'); } + .nav-icon-sessions { background-image: url('../img/toggle-filelist.svg?v=1'); } + .nav-icon-apppasswords { background-image: url('../img/password.svg?v=1'); } + .nav-icon-clientsbox { background-image: url('../img/change.svg?v=1'); } + .nav-icon-federated-cloud { background-image: url('../img/share.svg?v=1'); } + .nav-icon-second-factor-backup-codes { background-image: url('../img/password.svg?v=1'); } + .nav-icon-ssl-root-certificate { background-image: url('../img/password.svg?v=1'); } @@ -34,15 +45,19 @@ input#openid, input#webdav { width:20em; } min-width: 145px; padding-right: 0; } + #avatarform .avatardiv { margin-bottom: 10px; } + #avatarform .warning { width: 100%; } + #displayavatar { text-align: center; } + #displayavatar p { text-align: left; } @@ -53,9 +68,11 @@ input#openid, input#webdav { width:20em; } width: 33px; height: 33px; } + .jcrop-holder { z-index: 500; } + #cropper { float: left; z-index: 500; @@ -68,6 +85,7 @@ input#openid, input#webdav { width:20em; } width: 100%; height: calc(100% - 45px); } + #cropper .inner-container { z-index: 2001; /* above the top bar if needed */ position: absolute; @@ -84,9 +102,11 @@ input#openid, input#webdav { width:20em; } #cropper .inner-container .jcrop-holder { box-shadow: 0 0 7px #888; } + #cropper .inner-container .button { margin-top: 15px; } + #cropper .inner-container .primary { float: right; } @@ -94,6 +114,7 @@ input#openid, input#webdav { width:20em; } #personal-settings-avatar-container { float: left; } + #personal-settings-container { position: relative; float: left; @@ -101,22 +122,27 @@ input#openid, input#webdav { width:20em; } max-width: 700px; width: calc(100% - 200px); } + #personal-settings-container:after { clear: both; } + #personal-settings-container > div { float: left; height: 100px; min-width: 300px; } + #personal-settings-container.no-edit > div { height: 20px; min-width: 200px; } + #avatarform > h2, #personal-settings-container > div h2 { position: relative; } + #personal-settings-container > div h2 span[class^="icon-"], #personal-settings-avatar-container h2 span[class^="icon-"] { display: inline-block; @@ -127,11 +153,13 @@ input#openid, input#webdav { width:20em; } opacity: .3; cursor: pointer; } + .personal-settings-setting-box input[type="text"], .personal-settings-setting-box input[type="email"], .personal-settings-setting-box input[type="tel"] { width: 17em; } + #personal-settings-container > div > form span[class^="icon-checkmark"] { position: absolute; left: 228px; @@ -145,22 +173,27 @@ input#openid, input#webdav { width:20em; } right: 14px; top: 70px; } + #personal-settings-container .verify img { padding: 12px 7px 6px; } + /* only show pointer cursor when popup will be there */ #personal-settings-container .verify-action { cursor: pointer; } + .verification-dialog { display: none; right: -9px; top: 40px; width: 275px; } + .verification-dialog p { padding: 10px; } + .verification-dialog .verificationCode { font-family: monospace; display: block; @@ -171,16 +204,19 @@ input#openid, input#webdav { width:20em; } top: 44px; margin: -5px 0px 0; } + .federationScopeMenu.bubble::after { right: 50%; transform: translate(50%, 0); } + .federationScopeMenu.popovermenu a.menuitem, .federationScopeMenu.popovermenu label.menuitem, .federationScopeMenu.popovermenu .menuitem { font-size: 12.8px; line-height: 1.6em; } + .federationScopeMenu.popovermenu .menuitem .menuitem-text-detail { opacity: .75; } @@ -194,11 +230,13 @@ input#openid, input#webdav { width:20em; } padding-right: 0; min-width: 60%; } + #avatarform, #passwordform { margin-bottom: 0; padding-bottom: 0; } + #groups { overflow-wrap: break-word; max-width: 75%; @@ -213,17 +251,19 @@ input#openid, input#webdav { width:20em; } #sslCertificate tr.expired { background-color: rgba(255, 0, 0, 0.5); } + #sslCertificate td { padding: 5px; } - #displaynameerror { display: none; } + #displaynamechanged { display: none; } + input#identity { width: 20em; } @@ -237,6 +277,7 @@ input#identity { background-color: #47a447; padding: 3px; } + .msg.error { color: #fff; background-color: #d2322d; @@ -247,8 +288,13 @@ input#identity { display: inline-block; } -table.nostyle label { margin-right: 2em; } -table.nostyle td { padding: 0.2em 0; } +table.nostyle label { + margin-right: 2em; +} + +table.nostyle td { + padding: 0.2em 0; +} #sessions table, #apppasswords table { @@ -257,10 +303,12 @@ table.nostyle td { padding: 0.2em 0; } padding-top: 5px; max-width: 580px; } + #sessions table th, #apppasswords table th { opacity: .5; } + #sessions table th, #sessions table td, #apppasswords table th, @@ -286,10 +334,11 @@ table.nostyle td { padding: 0.2em 0; } position: relative; } -#sessions tr>*:nth-child(2), -#apppasswords tr>*:nth-child(2) { +#sessions tr > *:nth-child(2), +#apppasswords tr > *:nth-child(2) { text-align: right; } + #sessions .token-list td > a.icon, #apppasswords .token-list td > a.icon { opacity: 0; @@ -305,7 +354,7 @@ table.nostyle td { padding: 0.2em 0; } #sessions .token-list tr:hover td > a.icon, #apppasswords .token-list tr:hover td > a.icon, #sessions .token-list tr.active td > a.icon, -#apppasswords .token-list tr.active td > a.icon{ +#apppasswords .token-list tr.active td > a.icon { opacity: 0.6; } @@ -329,7 +378,7 @@ table.nostyle td { padding: 0.2em 0; } } #sessions .token-list tr.active div.configure > *, -#apppasswords .token-list tr.active div.configure > *{ +#apppasswords .token-list tr.active div.configure > * { margin-top: 5px; margin-bottom: 5px; display: inline-block; @@ -343,10 +392,11 @@ table.nostyle td { padding: 0.2em 0; } #new-app-login-name, #new-app-password { - width: 186px; + width: 245px; font-family: monospace; background-color: lightyellow; } + .app-password-row { display: table-row; } @@ -369,21 +419,29 @@ table.nostyle td { padding: 0.2em 0; } padding-left: 0 !important; margin-left: -10px } + .social-button img { padding: 10px; } - /* USERS */ -#newgroup-init a span { margin-left: 20px; } +#newgroup-init a span { + margin-left: 20px; +} + #newgroup-init a span:before { - position: absolute; left: 12px; top:-2px; - content: '+'; font-weight: bold; font-size: 150%; + position: absolute; + left: 12px; + top: -2px; + content: '+'; + font-weight: bold; + font-size: 150%; } #newgroup-form { height: 44px; } + #newgroupname { margin: 0; width: 100%; @@ -394,6 +452,7 @@ table.nostyle td { padding: 0.2em 0; } border-bottom: 1px solid #eee; border-radius: 0; } + #newgroup-form .button { position: absolute; right: 0; @@ -410,36 +469,70 @@ table.nostyle td { padding: 0.2em 0; } overflow: hidden; text-overflow: ellipsis; } + .isgroup.active .groupname { width: 65%; } -.usercount { float: left; margin: 5px; } +.usercount { + float: left; + margin: 5px; +} + li.active span.utils .delete { - float: left; position: relative; opacity: 0.5; - top: -7px; left: 7px; width: 44px; height: 44px; + float: left; + position: relative; + opacity: 0.5; + top: -7px; + left: 7px; + width: 44px; + height: 44px; } + li.active .rename { padding: 8px 14px 20px 14px; - top: 0px; position: absolute; width: 16px; height: 16px; + top: 0px; + position: absolute; + width: 16px; + height: 16px; opacity: 0.5; display: inline-block !important; } -li.active span.utils .delete img { margin: 14px; } -li.active .rename { opacity: 0.5; } -li.active span.utils .delete:hover, li.active .rename:hover { opacity: 1; } -span.utils .delete, .rename { display: none; } + +li.active span.utils .delete img { + margin: 14px; +} + +li.active .rename { + opacity: 0.5; +} + +li.active span.utils .delete:hover, li.active .rename:hover { + opacity: 1; +} + +span.utils .delete, .rename { + display: none; +} + #app-navigation ul li.active > span.utils .delete, -#app-navigation ul li.active > span.utils .rename { display: block; } +#app-navigation ul li.active > span.utils .rename { + display: block; +} + #usersearchform { position: absolute; top: 2px; right: 0; } + #usersearchform input { width: 150px; } -#usersearchform label { font-weight: 700; } + +#usersearchform label { + font-weight: 700; +} /* display table at full width */ table.grid { @@ -450,6 +543,7 @@ table.grid th { height: 2em; color: #999; } + table.grid th, table.grid td { border-bottom: 1px solid #eee; padding: 0 .5em; @@ -457,11 +551,28 @@ table.grid th, table.grid td { text-align: left; font-weight: normal; } -td.name, td.password { padding-left:.8em; } -td.password>img,td.displayName>img, td.quota>img { visibility:hidden; } -td.password, td.quota, td.displayName { width:12em; cursor:pointer; } -td.password>span, td.quota>span { margin-right: 1.2em; color: #C7C7C7; } -span.usersLastLoginTooltip { white-space: nowrap; } + +td.name, td.password { + padding-left: .8em; +} + +td.password > img, td.displayName > img, td.quota > img { + visibility: hidden; +} + +td.password, td.quota, td.displayName { + width: 12em; + cursor: pointer; +} + +td.password > span, td.quota > span { + margin-right: 1.2em; + color: #C7C7C7; +} + +span.usersLastLoginTooltip { + white-space: nowrap; +} /* dropdowns will be relative to this element */ #userlist { @@ -472,7 +583,7 @@ span.usersLastLoginTooltip { white-space: nowrap; } #userlist .storageLocation, #userlist .userBackend, #userlist .lastLogin { - display : none; + display: none; } /* because of accessibility the name cell is <th> - therefore we enforce the black color */ @@ -503,10 +614,11 @@ span.usersLastLoginTooltip { white-space: nowrap; } } .bubble { - z-index:1; + z-index: 1; right: -6px; top: auto; } + .bubble:after { right: 5px; } @@ -521,63 +633,111 @@ span.usersLastLoginTooltip { white-space: nowrap; } #userlist .popovermenu { margin-top: 4px; border-top-right-radius: 3px; + right: 3px; + opacity: 0; + display: block; + visibility: hidden; + transition: opacity 0.1s, visibility 0.1s; +} + +#userlist tr.active .popovermenu { + opacity: 1; + visibility: visible; +} + +#userlist .popovermenu > ul.userActionsMenu { + right: 15px; } -#userlist .popovermenu>ul.userActionsMenu { - right: 10px; +#userlist .popovermenu > ul.userActionsMenu a { + margin: 5px 0; } -#userlist .popovermenu>ul.userActionsMenu a span { +#userlist .popovermenu > ul.userActionsMenu a span:last-child { margin-left: 5px; } -#userlist .popovermenu { - display:none; +tr:hover > td.password > span, tr:hover > td.displayName > span { + margin: 0; + cursor: pointer; +} + +tr:hover > td.password > img, tr:hover > td.displayName > img, tr:hover > td.quota > img { + visibility: visible; + cursor: pointer; } -tr:hover>td.password>span, tr:hover>td.displayName>span { margin:0; cursor:pointer; } -tr:hover>td.password>img,tr:hover>td.displayName>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; } td.userActions { width: 25px; text-align: center; } + td.userActions .action { position: relative; top: 3px; } + +tr.active td.userActions .action { + opacity: 1; +} + td.userActions .action:hover { cursor: pointer; } -div.recoveryPassword { left:50em; display:block; position:absolute; top:-1px; } -input#recoveryPassword {width:15em;} +div.recoveryPassword { + left: 50em; + display: block; + position: absolute; + top: -1px; +} + +input#recoveryPassword { + width: 15em; +} + #controls select.quota { margin: 3px; margin-right: 10px; height: 37px; } -select.quota-user { position:relative; left:0; top:0; width:10em; } -select.quota.active { background: #fff; } -input.userFilter {width: 200px;} +select.quota-user { + position: relative; + left: 0; + top: 0; + width: 10em; +} + +select.quota.active { + background: #fff; +} + +input.userFilter { + width: 200px; +} /* positioning fixes */ #newuser { padding-left: 3px; } + #newuser .multiselect { min-width: 150px !important; } + #newuser .multiselect, #newusergroups + input[type='submit'] { position: relative; top: -1px; } + #headerGroups, #headerSubAdmins, #headerQuota { padding-left: 18px; } + #headerAvatar { width: 32px; } @@ -587,7 +747,6 @@ input.userFilter {width: 200px;} background-color: #FDD; } - /* APPS */ /* Bundle header */ @@ -595,21 +754,25 @@ input.userFilter {width: 200px;} display: table-row; position: relative; } + #apps-list .apps-header div { display: table-cell; height: 70px; } + #apps-list .apps-header h2 { display: table-cell; position: absolute; padding-left: 6px; padding-top: 15px; } + #apps-list .apps-header h2 .enable { position: relative; top: -1px; margin-left: 12px; } + #apps-list .apps-header h2 + .section { margin-top: 50px; } @@ -624,10 +787,14 @@ input.userFilter {width: 200px;} margin-bottom: 20px; } -.appinfo { margin: 1em 40px; } +.appinfo { + margin: 1em 40px; +} + #app-navigation .appwarning { background: #fcc; } + #app-navigation.appwarning:hover { background: #fbb; } @@ -640,12 +807,13 @@ span.version { #app-navigation .app-external, .app-version { - color: rgba(85,85,85,.5); + color: rgba(85, 85, 85, .5); } .app-level { margin-top: 8px; } + .app-level span { color: #555; background-color: transparent; @@ -653,10 +821,12 @@ span.version { border-radius: 3px; padding: 3px 6px; } + .app-level a { padding: 10px; white-space: nowrap; } + .app-level .official { border-color: #37ce02; background-position: left center; @@ -677,6 +847,7 @@ span.version { flex-wrap: wrap; align-content: flex-start; } + #apps-list.hidden { display: none; } @@ -686,6 +857,7 @@ span.version { flex: 0 0 auto; margin-left: 20px; } + #apps-list .section.apps-experimental { flex-basis: 90%; } @@ -693,16 +865,20 @@ span.version { #apps-list .app-description p { margin: 10px 0; } + #apps-list .app-description ul { list-style: disc; } + #apps-list .app-description ol { list-style: decimal; } + #apps-list .app-description > ul, #apps-list .app-description > ol { margin-left: 19px; } + #apps-list .app-description ol ol, #apps-list .app-description ol ul, #apps-list .app-description ul ol, @@ -715,6 +891,7 @@ span.version { width: 22%; box-sizing: border-box; } + #apps-list .section:nth-child(4n) { margin-right: 20px; } @@ -725,6 +902,7 @@ span.version { width: 30%; box-sizing: border-box; } + #apps-list .section:nth-child(3n) { margin-right: 20px; } @@ -735,6 +913,7 @@ span.version { width: 40%; box-sizing: border-box; } + #apps-list .section:nth-child(2n) { margin-right: 20px; } @@ -747,6 +926,7 @@ span.version { display: none !important; } } + @media only screen and (max-width: 700px) { #apps-list.installed .app-groups { display: none !important; @@ -757,9 +937,11 @@ span.version { display: block; margin: 8px 0; } + form.section { position: relative; } + .followupsection { display: block; padding: 0 30px 30px 30px; @@ -768,12 +950,14 @@ form.section { margin-top: -30px; position: relative; } + .app-image { position: relative; height: 150px; opacity: 1; overflow: hidden; } + .app-name, .app-version, .app-score, @@ -789,6 +973,7 @@ form.section { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; opacity: .5; } + .app-description-container { clear: both; position: relative; @@ -806,6 +991,7 @@ form.section { #app-category-1 { margin-bottom: 18px; } + /* capitalize "Other" category */ #app-category-925 { text-transform: capitalize; @@ -822,10 +1008,19 @@ form.section { } /* Transition to complete width! */ -.app:hover, .app:active { max-width: inherit; } +.app:hover, .app:active { + max-width: inherit; +} -.appslink { text-decoration: underline; } -.score { color:#666; font-weight:bold; font-size:0.8em; } +.appslink { + text-decoration: underline; +} + +.score { + color: #666; + font-weight: bold; + font-size: 0.8em; +} .appinfo .documentation { margin-top: 1em; @@ -845,7 +1040,7 @@ form.section { margin: 0; } -#apps-list.installed .section > *{ +#apps-list.installed .section > * { display: table-cell; height: initial; vertical-align: middle; @@ -884,20 +1079,25 @@ form.section { } #apps-list.installed .groups-enable label { - margin-right: 3px; + margin-right: 3px; } /* LOG */ #log { - white-space:normal; + white-space: normal; margin-bottom: 14px; } -#lessLog { display:none; } -table.grid td.date{ + +#lessLog { + display: none; +} + +table.grid td.date { white-space: nowrap; } + #log-section p { - margin-top:20px; + margin-top: 20px; } /* ADMIN */ @@ -908,6 +1108,7 @@ table.grid td.date{ margin-right: 6px; width: 16px; } + #app-navigation li span.no-icon { padding-left: 32px; } @@ -916,20 +1117,29 @@ table.grid td.date{ list-style: initial; margin: 10px 0; } + #security-warning-state span { padding-left: 25px; background-position: 5px center; margin-left: -5px; } -#shareAPI p { padding-bottom: 0.8em; } -#shareAPI input#shareapiExpireAfterNDays {width: 25px;} +#shareAPI p { + padding-bottom: 0.8em; +} + +#shareAPI input#shareapiExpireAfterNDays { + width: 25px; +} + #shareAPI .indent { padding-left: 28px; } + #shareAPI .double-indent { padding-left: 56px; } + #fileSharingSettings h3 { display: inline-block; } @@ -947,6 +1157,7 @@ table.grid td.date{ padding: 11px 20px; vertical-align: text-bottom; } + #shareAPI h2, #encryptionAPI h2, #mail_general_settings h2 { @@ -964,9 +1175,11 @@ table.grid td.date{ width: 300px; text-align: right; } + .mail_settings p select:nth-child(2) { width: 143px; } + #mail_smtpport { width: 40px; } @@ -974,12 +1187,14 @@ table.grid td.date{ .cronlog { margin-left: 10px; } + .status { display: inline-block; height: 16px; width: 16px; vertical-align: text-bottom; } + .status.success { border-radius: 50%; } @@ -1002,9 +1217,11 @@ span.success { background: #37ce02; border-radius: 3px; } + span.error { background: #ce3702; } + span.indeterminate { background: #e6db00; border-radius: 40% 0; @@ -1032,7 +1249,6 @@ doesnotexist:-o-prefocus, .strengthify-wrapper { font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; } - /* HELP */ .help-includes { @@ -1062,6 +1278,7 @@ doesnotexist:-o-prefocus, .strengthify-wrapper { #admin-tips li { list-style: initial; } + #admin-tips li a { display: inline-block; padding: 3px 0; diff --git a/settings/js/users/users.js b/settings/js/users/users.js index 387709cd64c..dccbcc0ce1e 100644 --- a/settings/js/users/users.js +++ b/settings/js/users/users.js @@ -908,21 +908,24 @@ $(document).ready(function () { event.stopPropagation(); var $td = $(this).closest('td'); var $tr = $($td).closest('tr'); - var menudiv = $td.find('.popovermenu'); + var menudiv = $tr.find('.popovermenu'); - if(menudiv.is(':visible')) { - menudiv.fadeOut(100); + if($tr.is('.active')) { + $tr.removeClass('active'); return; } + $('#userlist tr.active').removeClass('active'); menudiv.find('.action-togglestate').empty(); if($tr.data('userEnabled')) { $('.action-togglestate', $td).html('<span class="icon icon-close"></span><span>'+t('settings', 'Disable')+'</span>'); } else { $('.action-togglestate', $td).html('<span class="icon icon-add"></span><span>'+t('settings', 'Enable')+'</span>'); } - menudiv.click(function() { menudiv.fadeOut(100); }); - menudiv.hover('', function() { menudiv.fadeOut(100); }); - menudiv.fadeIn(100); + $tr.addClass('active'); + }); + + $(document.body).click(function() { + $('#userlist tr.active').removeClass('active'); }); $userListBody.on('click', '.action-togglestate', function (event) { diff --git a/tests/Settings/Controller/AuthSettingsControllerTest.php b/tests/Settings/Controller/AuthSettingsControllerTest.php index 7f4277acd73..5c1280ff4b0 100644 --- a/tests/Settings/Controller/AuthSettingsControllerTest.php +++ b/tests/Settings/Controller/AuthSettingsControllerTest.php @@ -133,11 +133,11 @@ class AuthSettingsControllerTest extends TestCase { ->method('getLoginName') ->will($this->returnValue('User13')); - $this->secureRandom->expects($this->exactly(4)) + $this->secureRandom->expects($this->exactly(5)) ->method('generate') - ->with(5, implode('', range('A', 'Z'))) + ->with(5, ISecureRandom::CHAR_HUMAN_READABLE) ->will($this->returnValue('XXXXX')); - $newToken = 'XXXXX-XXXXX-XXXXX-XXXXX'; + $newToken = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'; $this->tokenProvider->expects($this->once()) ->method('generateToken') diff --git a/version.php b/version.php index c1b989c8790..4f428c128aa 100644 --- a/version.php +++ b/version.php @@ -26,10 +26,10 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(12, 0, 0, 17); +$OC_Version = array(12, 0, 0, 18); // The human readable string -$OC_VersionString = '12.0 beta 1'; +$OC_VersionString = '12.0 beta 2'; $OC_VersionCanBeUpgradedFrom = [ 'nextcloud' => [ |