diff options
69 files changed, 1434 insertions, 108 deletions
diff --git a/.gitignore b/.gitignore index e7ced4b393f..69b977aee03 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ !/apps/provisioning_api !/apps/systemtags !/apps/testing +!/apps/admin_audit !/apps/updatenotification /apps/files_external/3rdparty/irodsphp/PHPUnitTest /apps/files_external/3rdparty/irodsphp/web diff --git a/.htaccess b/.htaccess index 5bf7b321f0c..bd9f5af3f70 100644 --- a/.htaccess +++ b/.htaccess @@ -56,9 +56,9 @@ RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L] RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L] RewriteRule ^remote/(.*) remote.php [QSA,L] - RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] + RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.* - RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] + RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L] </IfModule> <IfModule mod_mime.c> AddType image/svg+xml svg svgz diff --git a/README.md b/README.md index a23cb4271ea..7ca7d5fcbfc 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ if you want to join the Github organization just let us know and we’ll add you *This is by the community, for the community. Everyone is welcome! :)* - + ## Why is this so awesome? * :file_folder: **Access your Data** You can store your files, contacts, calendars and more on a server of your choosing. diff --git a/apps/admin_audit/appinfo/app.php b/apps/admin_audit/appinfo/app.php new file mode 100644 index 00000000000..ea5fb0286bf --- /dev/null +++ b/apps/admin_audit/appinfo/app.php @@ -0,0 +1,27 @@ +<?php +/** + * @author Lukas Reschke <lukas@statuscode.ch> + * + * @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/>. + * + */ + +$logger = \OC::$server->getLogger(); +$userSession = \OC::$server->getUserSession(); +$groupManager = \OC::$server->getGroupManager(); + +$auditLogger = new \OCA\Admin_Audit\AuditLogger($logger, $userSession, $groupManager); +$auditLogger->registerHooks(); diff --git a/apps/admin_audit/appinfo/info.xml b/apps/admin_audit/appinfo/info.xml new file mode 100644 index 00000000000..74fc880c881 --- /dev/null +++ b/apps/admin_audit/appinfo/info.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<info> + <id>admin_audit</id> + <name>Auditing / Logging</name> + <description>Provides logging abilities for Nextcloud such as logging file + accesses or otherwise sensitive actions. + </description> + <licence>AGPL</licence> + <author>Nextcloud</author> + <version>1.0.0</version> + <dependencies> + <owncloud min-version="9.0" max-version="9.1" /> + </dependencies> + <types> + <logging/> + </types> + <default_enable/> +</info> diff --git a/apps/admin_audit/lib/actions/action.php b/apps/admin_audit/lib/actions/action.php new file mode 100644 index 00000000000..6aafacc6189 --- /dev/null +++ b/apps/admin_audit/lib/actions/action.php @@ -0,0 +1,76 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Admin_Audit\Actions; + +use OCP\ILogger; + +class Action { + /** @var ILogger */ + private $logger; + + /** + * @param ILogger $logger + */ + public function __construct(ILogger $logger) { + $this->logger = $logger; + } + + /** + * Log a single action with a log level of info + * + * @param string $text + * @param array $params + * @param array $elements + */ + public function log($text, + array $params, + array $elements) { + foreach($elements as $element) { + if(!isset($params[$element])) { + $this->logger->critical( + sprintf( + '$params["'.$element.'"] was missing. Transferred value: %s', + print_r($params, true) + ) + ); + return; + } + } + + $replaceArray = []; + foreach($elements as $element) { + if($params[$element] instanceof \DateTime) { + $params[$element] = $params[$element]->format('Y-m-d H:i:s'); + } + $replaceArray[] = $params[$element]; + } + + $this->logger->info( + vsprintf( + $text, + $replaceArray + ), + [ + 'app' => 'admin_audit' + ] + ); + } +} diff --git a/apps/admin_audit/lib/actions/auth.php b/apps/admin_audit/lib/actions/auth.php new file mode 100644 index 00000000000..4061ca89c4b --- /dev/null +++ b/apps/admin_audit/lib/actions/auth.php @@ -0,0 +1,56 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Admin_Audit\Actions; + +/** + * Class Auth logs all auth related actions + * + * @package OCA\Admin_Audit\Actions + */ +class Auth extends Action { + public function loginAttempt(array $params) { + $this->log( + 'Login attempt: "%s"', + $params, + [ + 'uid', + ] + ); + } + + public function loginSuccessful(array $params) { + $this->log( + 'Login successful: "%s"', + $params, + [ + 'uid', + ] + ); + } + + public function logout(array $params) { + $this->log( + 'Logout occurred', + [], + [] + ); + } +} diff --git a/apps/admin_audit/lib/actions/files.php b/apps/admin_audit/lib/actions/files.php new file mode 100644 index 00000000000..46da0ade6bb --- /dev/null +++ b/apps/admin_audit/lib/actions/files.php @@ -0,0 +1,135 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Admin_Audit\Actions; + +/** + * Class Files logs the actions to files + * + * @package OCA\Admin_Audit\Actions + */ +class Files extends Action { + /** + * Logs file read actions + * + * @param array $params + */ + public function read(array $params) { + $this->log( + 'File accessed: "%s"', + $params, + [ + 'path', + ] + ); + } + + /** + * Logs rename actions of files + * + * @param array $params + */ + public function rename(array $params) { + $this->log( + 'File renamed: "%s" to "%s"', + $params, + [ + 'oldpath', + 'newpath', + ] + ); + } + + /** + * Logs creation of files + * + * @param array $params + */ + public function create(array $params) { + $this->log( + 'File created: "%s"', + $params, + [ + 'path', + ] + ); + } + + /** + * Logs copying of files + * + * @param array $params + */ + public function copy(array $params) { + $this->log( + 'File copied: "%s" to "%s"', + $params, + [ + 'oldpath', + 'newpath', + ] + ); + } + + /** + * Logs writing of files + * + * @param array $params + */ + public function write(array $params) { + $this->log( + 'File written to: "%s"', + $params, + [ + 'path', + ] + ); + } + + /** + * Logs update of files + * + * @param array $params + */ + public function update(array $params) { + $this->log( + 'File updated: "%s"', + $params, + [ + 'path', + ] + ); + } + + /** + * Logs deletions of files + * + * @param array $params + */ + public function delete(array $params) { + $this->log( + 'File deleted: "%s"', + $params, + [ + 'path', + ] + ); + } +} diff --git a/apps/admin_audit/lib/actions/groupmanagement.php b/apps/admin_audit/lib/actions/groupmanagement.php new file mode 100644 index 00000000000..4ece8994f39 --- /dev/null +++ b/apps/admin_audit/lib/actions/groupmanagement.php @@ -0,0 +1,73 @@ +<?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\Admin_Audit\Actions; + + +use OCA\Admin_Audit\Actions\Action; +use OCP\IGroup; +use OCP\IUser; + +/** + * Class GroupManagement logs all group manager related events + * + * @package OCA\Admin_Audit + */ +class GroupManagement extends Action { + + /** + * log add user to group event + * + * @param IGroup $group + * @param IUser $user + */ + public function addUser(IGroup $group, IUser $user) { + $this->log('User "%s" added to group "%s"', + [ + 'group' => $group->getGID(), + 'user' => $user->getUID() + ], + [ + 'user', 'group' + ] + ); + } + + /** + * log remove user from group event + * + * @param IGroup $group + * @param IUser $user + */ + public function removeUser(IGroup $group, IUser $user) { + $this->log('User "%s" removed from group "%s"', + [ + 'group' => $group->getGID(), + 'user' => $user->getUID() + ], + [ + 'user', 'group' + ] + ); + } + +} diff --git a/apps/admin_audit/lib/actions/sharing.php b/apps/admin_audit/lib/actions/sharing.php new file mode 100644 index 00000000000..5f263748465 --- /dev/null +++ b/apps/admin_audit/lib/actions/sharing.php @@ -0,0 +1,189 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Admin_Audit\Actions; +use OCP\Share; + +/** + * Class Sharing logs the sharing actions + * + * @package OCA\Admin_Audit\Actions + */ +class Sharing extends Action { + /** + * Logs sharing of data + * + * @param array $params + */ + public function shared(array $params) { + if($params['shareType'] === Share::SHARE_TYPE_LINK) { + $this->log( + 'The %s "%s" with ID "%s" has been shared via link with permissions "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'itemTarget', + 'itemSource', + 'permissions', + 'id', + ] + ); + } elseif($params['shareType'] === Share::SHARE_TYPE_USER) { + $this->log( + 'The %s "%s" with ID "%s" has been shared to the user "%s" with permissions "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'itemTarget', + 'itemSource', + 'shareWith', + 'permissions', + 'id', + ] + ); + } elseif($params['shareType'] === Share::SHARE_TYPE_GROUP) { + $this->log( + 'The %s "%s" with ID "%s" has been shared to the group "%s" with permissions "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'itemTarget', + 'itemSource', + 'shareWith', + 'permissions', + 'id', + ] + ); + } + } + + /** + * Logs unsharing of data + * + * @param array $params + */ + public function unshare(array $params) { + if($params['shareType'] === Share::SHARE_TYPE_LINK) { + $this->log( + 'The %s "%s" with ID "%s" has been unshared (Share ID: %s)', + $params, + [ + 'itemType', + 'fileTarget', + 'itemSource', + 'id', + ] + ); + } elseif($params['shareType'] === Share::SHARE_TYPE_USER) { + $this->log( + 'The %s "%s" with ID "%s" has been unshared from the user "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'fileTarget', + 'itemSource', + 'shareWith', + 'id', + ] + ); + } elseif($params['shareType'] === Share::SHARE_TYPE_GROUP) { + $this->log( + 'The %s "%s" with ID "%s" has been unshared from the group "%s" (Share ID: %s)', + $params, + [ + 'itemType', + 'fileTarget', + 'itemSource', + 'shareWith', + 'id', + ] + ); + } + } + + /** + * Logs the updating of permission changes for shares + * + * @param array $params + */ + public function updatePermissions(array $params) { + $this->log( + 'The permissions of the shared %s "%s" with ID "%s" have been changed to "%s"', + $params, + [ + 'itemType', + 'path', + 'itemSource', + 'permissions', + ] + ); + } + + /** + * Logs the password changes for a share + * + * @param array $params + */ + public function updatePassword(array $params) { + $this->log( + 'The password of the publicly shared %s "%s" with ID "%s" has been changed', + $params, + [ + 'itemType', + 'token', + 'itemSource', + ] + ); + } + + /** + * Logs the expiration date changes for a share + * + * @param array $params + */ + public function updateExpirationDate(array $params) { + $this->log( + 'The expiration date of the publicly shared %s with ID "%s" has been changed to "%s"', + $params, + [ + 'itemType', + 'itemSource', + 'date', + ] + ); + } + + /** + * Logs access of shared files + * + * @param array $params + */ + public function shareAccessed(array $params) { + $this->log( + 'The shared %s with the token "%s" by "%s" has been accessed.', + $params, + [ + 'itemType', + 'token', + 'uidOwner', + ] + ); + } +} diff --git a/apps/admin_audit/lib/actions/trashbin.php b/apps/admin_audit/lib/actions/trashbin.php new file mode 100644 index 00000000000..2cd3189d064 --- /dev/null +++ b/apps/admin_audit/lib/actions/trashbin.php @@ -0,0 +1,69 @@ +<?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\Admin_Audit\Actions; + + +use OCP\ILogger; +use OCP\IUserSession; + +class Trashbin extends Action { + + /** @var IUserSession */ + private $userSession; + + /** + * Trashbin constructor. + * + * @param ILogger $logger + * @param IUserSession $userSession + */ + public function __construct(ILogger $logger, IUserSession $userSession) { + parent::__construct($logger); + $this->userSession = $userSession; + } + + public function delete($params) { + $this->log('File "%s" deleted from trash bin by "%s"', + [ + 'path' => $params['path'], + 'user' => $this->userSession->getUser()->getUID() + ], + [ + 'path', 'user' + ] + ); + } + + public function restore($params) { + $this->log('File "%s" restored from trash bin by "%s"', + [ + 'path' => $params['filePath'], + 'user' => $this->userSession->getUser()->getUID() + ], + [ + 'path', 'user' + ] + ); + } + +} diff --git a/apps/admin_audit/lib/actions/usermanagement.php b/apps/admin_audit/lib/actions/usermanagement.php new file mode 100644 index 00000000000..5005d150961 --- /dev/null +++ b/apps/admin_audit/lib/actions/usermanagement.php @@ -0,0 +1,78 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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\Admin_Audit\Actions; +use OCP\IUser; + +/** + * Class UserManagement logs all user management related actions. + * + * @package OCA\Admin_Audit\Actions + */ +class UserManagement extends Action { + /** + * Log creation of users + * + * @param array $params + */ + public function create(array $params) { + $this->log( + 'User created: "%s"', + $params, + [ + 'uid', + ] + ); + } + + /** + * Log deletion of users + * + * @param array $params + */ + public function delete(array $params) { + $this->log( + 'User deleted: "%s"', + $params, + [ + 'uid', + ] + ); + } + + /** + * Logs changing of the user scope + * + * @param IUser $user + */ + public function setPassword(IUser $user) { + if($user->getBackendClassName() === 'Database') { + $this->log( + 'Password of user "%s" has been changed', + [ + 'user' => $user->getUID(), + ], + [ + 'user', + ] + ); + } + } +} diff --git a/apps/admin_audit/lib/actions/versions.php b/apps/admin_audit/lib/actions/versions.php new file mode 100644 index 00000000000..006c33bf04f --- /dev/null +++ b/apps/admin_audit/lib/actions/versions.php @@ -0,0 +1,45 @@ +<?php +/** + * @copyright 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\Admin_Audit\Actions; + + +class Versions extends Action { + + public function rollback($params) { + $this->log('Version "%s" of "%s" was restored.', + [ + 'version' => $params['revision'], + 'path' => $params['path'] + ], + ['version', 'path'] + ); + } + + public function delete($params) { + $this->log('Version "%s" was deleted.', + ['path' => $params['path']], + ['path'] + ); + } + +} diff --git a/apps/admin_audit/lib/auditlogger.php b/apps/admin_audit/lib/auditlogger.php new file mode 100644 index 00000000000..f7dae10701f --- /dev/null +++ b/apps/admin_audit/lib/auditlogger.php @@ -0,0 +1,186 @@ +<?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\Admin_Audit; + + +use OC\Files\Filesystem; +use OCA\Admin_Audit\Actions\Auth; +use OCA\Admin_Audit\Actions\Files; +use OCA\Admin_Audit\Actions\GroupManagement; +use OCA\Admin_Audit\Actions\Sharing; +use OCA\Admin_Audit\Actions\Trashbin; +use OCA\Admin_Audit\Actions\UserManagement; +use OCA\Admin_Audit\Actions\Versions; +use OCP\IGroupManager; +use OCP\ILogger; +use OCP\IUserSession; +use OCP\Util; + +class AuditLogger { + + /** @var ILogger */ + private $logger; + + /** @var IUserSession */ + private $userSession; + + /** @var IGroupManager */ + private $groupManager; + + /** + * AuditLogger constructor. + * + * @param ILogger $logger + * @param IUserSession $userSession + * @param IGroupManager $groupManager + */ + public function __construct(ILogger $logger, + IUserSession $userSession, + IGroupManager $groupManager) { + $this->logger = $logger; + $this->userSession = $userSession; + $this->groupManager = $groupManager; + } + + /** + * register hooks in order to log them + */ + public function registerHooks() { + $this->userManagementHooks(); + $this->groupHooks(); + $this->sharingHooks(); + $this->authHooks(); + $this->fileHooks(); + $this->trashbinHooks(); + $this->versionsHooks(); + } + + /** + * connect to user management hooks + */ + private function userManagementHooks() { + $userActions = new UserManagement($this->logger); + + Util::connectHook('OC_User', 'post_createUser', $userActions, 'create'); + Util::connectHook('OC_User', 'post_deleteUser', $userActions, 'delete'); + $this->userSession->listen('\OC\User', 'postSetPassword', [$userActions, 'setPassword']); + } + + private function groupHooks() { + $groupActions = new GroupManagement($this->logger); + $this->groupManager->listen('\OC\Group', 'postRemoveUser', [$groupActions, 'removeUser']); + $this->groupManager->listen('\OC\Group', 'postAddUser', [$groupActions, 'addUser']); + } + + /** + * connect to sharing events + */ + private function sharingHooks() { + $shareActions = new Sharing($this->logger); + + Util::connectHook('OCP\Share', 'post_shared', $shareActions, 'shared'); + Util::connectHook('OCP\Share', 'post_unshare', $shareActions, 'unshare'); + Util::connectHook('OCP\Share', 'post_update_permissions', $shareActions, 'updatePermissions'); + Util::connectHook('OCP\Share', 'post_update_password', $shareActions, 'updatePassword'); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $shareActions, 'updateExpirationDate'); + Util::connectHook('OCP\Share', 'share_link_access', $shareActions, 'shareAccessed'); + } + + /** + * connect to authentication event and related actions + */ + private function authHooks() { + $authActions = new Auth($this->logger); + + Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt'); + Util::connectHook('OC_User', 'post_login', $authActions, 'loginSuccessful'); + Util::connectHook('OC_User', 'logout', $authActions, 'logout'); + } + + + /** + * connect to file hooks + */ + private function fileHooks() { + $fileActions = new Files($this->logger); + + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_post_rename, + $fileActions, + 'rename' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_post_create, + $fileActions, + 'create' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_post_copy, + $fileActions, + 'copy' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_post_write, + $fileActions, + 'write' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_post_update, + $fileActions, + 'update' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_read, + $fileActions, + 'read' + ); + Util::connectHook( + Filesystem::CLASSNAME, + Filesystem::signal_delete, + $fileActions, + 'delete' + ); + } + + public function versionsHooks() { + $versionsActions = new Versions($this->logger); + Util::connectHook('\OCP\Versions', 'rollback', $versionsActions, 'rollback'); + Util::connectHook('\OCP\Versions', 'delete',$versionsActions, 'delete'); + } + + /** + * connect to trash bin hooks + */ + private function trashbinHooks() { + $trashActions = new Trashbin($this->logger, $this->userSession); + Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete'); + Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore'); + } + +} diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php index 7b959a0d899..27900cc1cad 100644 --- a/apps/dav/lib/Connector/Sabre/Auth.php +++ b/apps/dav/lib/Connector/Sabre/Auth.php @@ -110,10 +110,10 @@ class Auth extends AbstractBasic { $this->session->close(); return true; } else { - \OC_Util::setUpFS(); //login hooks may need early access to the filesystem + \OC_Util::setupFS(); //login hooks may need early access to the filesystem if($this->userSession->logClientIn($username, $password)) { $this->userSession->createSessionToken($this->request, $this->userSession->getUser()->getUID(), $username, $password); - \OC_Util::setUpFS($this->userSession->getUser()->getUID()); + \OC_Util::setupFS($this->userSession->getUser()->getUID()); $this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID()); $this->session->close(); return true; diff --git a/apps/federatedfilesharing/l10n/pl.js b/apps/federatedfilesharing/l10n/pl.js index 9bd5edd9b56..1d8b949c74a 100644 --- a/apps/federatedfilesharing/l10n/pl.js +++ b/apps/federatedfilesharing/l10n/pl.js @@ -2,6 +2,7 @@ OC.L10N.register( "federatedfilesharing", { "Sharing %s failed, because this item is already shared with %s" : "Współdzielenie %s nie powiodło się, ponieważ element jest już współdzielony z %s", + "File is already shared with %s" : "Plik jest już współdzielony z %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Współdzielenie %s nie powiodło się, nie można odnaleźć %s. Prawdopobnie serwer nie jest teraz osiągalny.", "Accept" : "Akceptuj", "Open documentation" : "Otwórz dokumentację", diff --git a/apps/federatedfilesharing/l10n/pl.json b/apps/federatedfilesharing/l10n/pl.json index 5fd8fb130b7..c44eecbeeb7 100644 --- a/apps/federatedfilesharing/l10n/pl.json +++ b/apps/federatedfilesharing/l10n/pl.json @@ -1,5 +1,6 @@ { "translations": { "Sharing %s failed, because this item is already shared with %s" : "Współdzielenie %s nie powiodło się, ponieważ element jest już współdzielony z %s", + "File is already shared with %s" : "Plik jest już współdzielony z %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Współdzielenie %s nie powiodło się, nie można odnaleźć %s. Prawdopobnie serwer nie jest teraz osiągalny.", "Accept" : "Akceptuj", "Open documentation" : "Otwórz dokumentację", diff --git a/apps/federation/css/settings-admin.css b/apps/federation/css/settings-admin.css index 55b1dd64d15..150412c156f 100644 --- a/apps/federation/css/settings-admin.css +++ b/apps/federation/css/settings-admin.css @@ -17,10 +17,13 @@ cursor: pointer; } -#listOfTrustedServers li:hover { - cursor: pointer; -} - #listOfTrustedServers .status { margin-right: 10px; } + +#listOfTrustedServers .icon { + cursor: pointer; + display: inline-block; + vertical-align: middle; + margin-left: 10px; +} diff --git a/apps/federation/js/settings-admin.js b/apps/federation/js/settings-admin.js index 7d531b39d8c..45d5d62a5a3 100644 --- a/apps/federation/js/settings-admin.js +++ b/apps/federation/js/settings-admin.js @@ -42,8 +42,9 @@ $(document).ready(function () { $('ul#listOfTrustedServers').prepend( $('<li>') .attr('id', data.id) - .attr('class', 'icon-delete') - .html('<span class="status indeterminate"></span>' + data.url) + .html('<span class="status indeterminate"></span>' + + data.url + + '<span class="icon icon-delete"></span>') ); OC.msg.finishedSuccess('#ocFederationAddServer .msg', data.message); }) @@ -56,10 +57,10 @@ $(document).ready(function () { } }); - // remove trusted server from list - $( "#listOfTrustedServers" ).on('click', 'li', function() { - var id = $(this).attr('id'); - var $this = $(this); +// remove trusted server from list + $( "#listOfTrustedServers" ).on('click', 'li > .icon-delete', function() { + var $this = $(this).parent(); + id = $this.attr('id'); $.ajax({ url: OC.generateUrl('/apps/federation/trusted-servers/' + id), type: 'DELETE', diff --git a/apps/federation/templates/settings-admin.php b/apps/federation/templates/settings-admin.php index 704fc9a9ace..ce66214de7c 100644 --- a/apps/federation/templates/settings-admin.php +++ b/apps/federation/templates/settings-admin.php @@ -23,7 +23,7 @@ style('federation', 'settings-admin') </p> <ul id="listOfTrustedServers"> <?php foreach($_['trustedServers'] as $trustedServer) { ?> - <li id="<?php p($trustedServer['id']); ?>" class="icon-delete"> + <li id="<?php p($trustedServer['id']); ?>"> <?php if((int)$trustedServer['status'] === TrustedServers::STATUS_OK) { ?> <span class="status success"></span> <?php @@ -36,6 +36,7 @@ style('federation', 'settings-admin') <span class="status error"></span> <?php } ?> <?php p($trustedServer['url']); ?> + <span class="icon icon-delete"></span> </li> <?php } ?> </ul> diff --git a/apps/files/l10n/pl.js b/apps/files/l10n/pl.js index 01259a538ab..cb243f6bf4d 100644 --- a/apps/files/l10n/pl.js +++ b/apps/files/l10n/pl.js @@ -45,6 +45,7 @@ OC.L10N.register( "Unable to determine date" : "Nie można ustalić daty", "This operation is forbidden" : "Ta operacja jest niedozwolona", "This directory is unavailable, please check the logs or contact the administrator" : "Ten folder jest niedostępny, proszę sprawdzić logi lub skontaktować się z administratorem.", + "Could not move \"{file}\", target exists" : "Nie można było przenieść „{file}” – plik o takiej nazwie już istnieje", "Could not move \"{file}\"" : "Nie można było przenieść \"{file}\"", "Could not create file \"{file}\"" : "Nie można było utworzyć pliku \"{file}\"", "Could not create file \"{file}\" because it already exists" : "Nie można było utworzyć pliku \"{file}\", ponieważ ten plik już istnieje.", diff --git a/apps/files/l10n/pl.json b/apps/files/l10n/pl.json index fd4d5116953..60323d0e757 100644 --- a/apps/files/l10n/pl.json +++ b/apps/files/l10n/pl.json @@ -43,6 +43,7 @@ "Unable to determine date" : "Nie można ustalić daty", "This operation is forbidden" : "Ta operacja jest niedozwolona", "This directory is unavailable, please check the logs or contact the administrator" : "Ten folder jest niedostępny, proszę sprawdzić logi lub skontaktować się z administratorem.", + "Could not move \"{file}\", target exists" : "Nie można było przenieść „{file}” – plik o takiej nazwie już istnieje", "Could not move \"{file}\"" : "Nie można było przenieść \"{file}\"", "Could not create file \"{file}\"" : "Nie można było utworzyć pliku \"{file}\"", "Could not create file \"{file}\" because it already exists" : "Nie można było utworzyć pliku \"{file}\", ponieważ ten plik już istnieje.", diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 8d2cb52d67c..2477f513db3 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -299,7 +299,8 @@ StorageConfig.prototype = { mountPoint: this.mountPoint, backend: this.backend, authMechanism: this.authMechanism, - backendOptions: this.backendOptions + backendOptions: this.backendOptions, + testOnly: true }; if (this.id) { data.id = this.id; @@ -326,6 +327,7 @@ StorageConfig.prototype = { $.ajax({ type: 'GET', url: OC.generateUrl(this._url + '/{id}', {id: this.id}), + data: {'testOnly': true}, success: options.success, error: options.error }); @@ -908,6 +910,7 @@ MountConfigListView.prototype = _.extend({ $.ajax({ type: 'GET', url: OC.generateUrl('apps/files_external/userglobalstorages'), + data: {'testOnly' : true}, contentType: 'application/json', success: function(result) { var onCompletion = jQuery.Deferred(); diff --git a/apps/files_external/js/statusmanager.js b/apps/files_external/js/statusmanager.js index 118ec17d246..91974f2d04d 100644 --- a/apps/files_external/js/statusmanager.js +++ b/apps/files_external/js/statusmanager.js @@ -78,6 +78,7 @@ OCA.External.StatusManager = { defObj = $.ajax({ type: 'GET', url: OC.webroot + '/index.php/apps/files_external/' + ((mountData.type === 'personal') ? 'userstorages' : 'userglobalstorages') + '/' + mountData.id, + data: {'testOnly' : false}, success: function (response) { if (response && response.status === 0) { self.mountStatus[mountData.mount_point] = response; diff --git a/apps/files_external/l10n/pl.js b/apps/files_external/l10n/pl.js index 0ba2646601b..8c3e394627e 100644 --- a/apps/files_external/l10n/pl.js +++ b/apps/files_external/l10n/pl.js @@ -2,6 +2,7 @@ OC.L10N.register( "files_external", { "Fetching access tokens failed. Verify that your app key and secret are correct." : "Otrzymano błędne żądanie tokenów. Sprawdź, czy klucz aplikacji oraz klucz poufny są poprawne.", + "Please provide a valid app key and secret." : "Proszę podać prawidłowy klucz aplikacji i klucz sekretny.", "Step 1 failed. Exception: %s" : "Krok 1 błędny. Błąd: %s", "Step 2 failed. Exception: %s" : "Krok 2 błędny. Błąd: %s", "External storage" : "Zewnętrzne zasoby dyskowe", diff --git a/apps/files_external/l10n/pl.json b/apps/files_external/l10n/pl.json index 8809813c9ba..8e00fc31863 100644 --- a/apps/files_external/l10n/pl.json +++ b/apps/files_external/l10n/pl.json @@ -1,5 +1,6 @@ { "translations": { "Fetching access tokens failed. Verify that your app key and secret are correct." : "Otrzymano błędne żądanie tokenów. Sprawdź, czy klucz aplikacji oraz klucz poufny są poprawne.", + "Please provide a valid app key and secret." : "Proszę podać prawidłowy klucz aplikacji i klucz sekretny.", "Step 1 failed. Exception: %s" : "Krok 1 błędny. Błąd: %s", "Step 2 failed. Exception: %s" : "Krok 2 błędny. Błąd: %s", "External storage" : "Zewnętrzne zasoby dyskowe", diff --git a/apps/files_external/lib/Controller/GlobalStoragesController.php b/apps/files_external/lib/Controller/GlobalStoragesController.php index 6f9278ce6f1..471e3b51593 100644 --- a/apps/files_external/lib/Controller/GlobalStoragesController.php +++ b/apps/files_external/lib/Controller/GlobalStoragesController.php @@ -139,7 +139,8 @@ class GlobalStoragesController extends StoragesController { $mountOptions, $applicableUsers, $applicableGroups, - $priority + $priority, + $testOnly = true ) { $storage = $this->createStorage( $mountPoint, @@ -172,7 +173,7 @@ class GlobalStoragesController extends StoragesController { ); } - $this->updateStorageStatus($storage); + $this->updateStorageStatus($storage, $testOnly); return new DataResponse( $storage, diff --git a/apps/files_external/lib/Controller/StoragesController.php b/apps/files_external/lib/Controller/StoragesController.php index aa6a04ecb8d..e50426f4888 100644 --- a/apps/files_external/lib/Controller/StoragesController.php +++ b/apps/files_external/lib/Controller/StoragesController.php @@ -238,7 +238,7 @@ abstract class StoragesController extends Controller { * * @param StorageConfig $storage storage configuration */ - protected function updateStorageStatus(StorageConfig &$storage) { + protected function updateStorageStatus(StorageConfig &$storage, $testOnly = true) { try { $this->manipulateStorageConfig($storage); @@ -249,7 +249,8 @@ abstract class StoragesController extends Controller { \OC_Mount_Config::getBackendStatus( $backend->getStorageClass(), $storage->getBackendOptions(), - false + false, + $testOnly ) ); } catch (InsufficientDataForMeaningfulAnswerException $e) { @@ -293,11 +294,11 @@ abstract class StoragesController extends Controller { * * @return DataResponse */ - public function show($id) { + public function show($id, $testOnly = true) { try { $storage = $this->service->getStorage($id); - $this->updateStorageStatus($storage); + $this->updateStorageStatus($storage, $testOnly); } catch (NotFoundException $e) { return new DataResponse( [ diff --git a/apps/files_external/lib/Controller/UserGlobalStoragesController.php b/apps/files_external/lib/Controller/UserGlobalStoragesController.php index 1c94a1e9635..f65e578507d 100644 --- a/apps/files_external/lib/Controller/UserGlobalStoragesController.php +++ b/apps/files_external/lib/Controller/UserGlobalStoragesController.php @@ -111,11 +111,11 @@ class UserGlobalStoragesController extends StoragesController { * * @NoAdminRequired */ - public function show($id) { + public function show($id, $testOnly = true) { try { $storage = $this->service->getStorage($id); - $this->updateStorageStatus($storage); + $this->updateStorageStatus($storage, $testOnly); } catch (NotFoundException $e) { return new DataResponse( [ @@ -146,7 +146,8 @@ class UserGlobalStoragesController extends StoragesController { */ public function update( $id, - $backendOptions + $backendOptions, + $testOnly = true ) { try { $storage = $this->service->getStorage($id); @@ -171,7 +172,7 @@ class UserGlobalStoragesController extends StoragesController { ); } - $this->updateStorageStatus($storage); + $this->updateStorageStatus($storage, $testOnly); $this->sanitizeStorage($storage); return new DataResponse( diff --git a/apps/files_external/lib/Controller/UserStoragesController.php b/apps/files_external/lib/Controller/UserStoragesController.php index 936da7ec5e2..28663090e89 100644 --- a/apps/files_external/lib/Controller/UserStoragesController.php +++ b/apps/files_external/lib/Controller/UserStoragesController.php @@ -101,8 +101,8 @@ class UserStoragesController extends StoragesController { * * {@inheritdoc} */ - public function show($id) { - return parent::show($id); + public function show($id, $testOnly = true) { + return parent::show($id, $testOnly); } /** @@ -170,7 +170,8 @@ class UserStoragesController extends StoragesController { $backend, $authMechanism, $backendOptions, - $mountOptions + $mountOptions, + $testOnly = true ) { $storage = $this->createStorage( $mountPoint, @@ -200,7 +201,7 @@ class UserStoragesController extends StoragesController { ); } - $this->updateStorageStatus($storage); + $this->updateStorageStatus($storage, $testOnly); return new DataResponse( $storage, diff --git a/apps/files_external/lib/Lib/Storage/Google.php b/apps/files_external/lib/Lib/Storage/Google.php index 49fde7d066f..96f12800c10 100644 --- a/apps/files_external/lib/Lib/Storage/Google.php +++ b/apps/files_external/lib/Lib/Storage/Google.php @@ -326,7 +326,7 @@ class Google extends \OC\Files\Storage\Common { $stat['size'] = 0; } else { // Check if this is a Google Doc - if ($this->getMimeType($path) !== $file->getMimeType()) { + if ($this->isGoogleDocFile($file)) { // Return unknown file size $stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN; } else { diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 86aafcf5770..3510b675d4d 100644 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -215,7 +215,7 @@ class OC_Mount_Config { * @return int see self::STATUS_* * @throws Exception */ - public static function getBackendStatus($class, $options, $isPersonal) { + public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) { if (self::$skipTest) { return StorageNotAvailableException::STATUS_SUCCESS; } @@ -228,7 +228,7 @@ class OC_Mount_Config { $storage = new $class($options); try { - $result = $storage->test($isPersonal); + $result = $storage->test($isPersonal, $testOnly); $storage->setAvailability($result); if ($result) { return StorageNotAvailableException::STATUS_SUCCESS; diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js index 7aa49b2c82a..8f01c16b38c 100644 --- a/apps/files_external/tests/js/settingsSpec.js +++ b/apps/files_external/tests/js/settingsSpec.js @@ -223,7 +223,8 @@ describe('OCA.External.Settings tests', function() { applicableGroups: [], mountOptions: { 'previews': true - } + }, + testOnly: true }); // TODO: respond and check data-id diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index a703ef087ee..ebdfe2aa738 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -21,6 +21,7 @@ OC.L10N.register( "Remote share password" : "Hasło do zdalnego zasobu", "Cancel" : "Anuluj", "Add remote share" : "Dodaj zdalny zasób", + "No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}", "Invalid ownCloud url" : "Błędny adres URL", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index 62d6ef25b38..f5de5dd368c 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -19,6 +19,7 @@ "Remote share password" : "Hasło do zdalnego zasobu", "Cancel" : "Anuluj", "Add remote share" : "Dodaj zdalny zasób", + "No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}", "Invalid ownCloud url" : "Błędny adres URL", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", diff --git a/apps/systemtags/l10n/pl.js b/apps/systemtags/l10n/pl.js index fc3616bff26..f5e4775d540 100644 --- a/apps/systemtags/l10n/pl.js +++ b/apps/systemtags/l10n/pl.js @@ -3,6 +3,8 @@ OC.L10N.register( { "Tags" : "Etykiety", "Tagged files" : "Otagowane pliki", + "Select tags to filter by" : "Wybierz tagi do filtru", + "Please select tags to filter by" : "Proszę wybrać tagi do filtrów", "No files found for the selected tags" : "Nie znaleziono plików dla wybranych etykiet", "<strong>System tags</strong> for a file have been modified" : "<strong>System etykiet</strong> dla pliku został zmieniony", "%1$s assigned system tag %3$s" : "%1$s przypisywalny system etykiet%3$s", diff --git a/apps/systemtags/l10n/pl.json b/apps/systemtags/l10n/pl.json index 543aa3be58c..6cb103ed4a5 100644 --- a/apps/systemtags/l10n/pl.json +++ b/apps/systemtags/l10n/pl.json @@ -1,6 +1,8 @@ { "translations": { "Tags" : "Etykiety", "Tagged files" : "Otagowane pliki", + "Select tags to filter by" : "Wybierz tagi do filtru", + "Please select tags to filter by" : "Proszę wybrać tagi do filtrów", "No files found for the selected tags" : "Nie znaleziono plików dla wybranych etykiet", "<strong>System tags</strong> for a file have been modified" : "<strong>System etykiet</strong> dla pliku został zmieniony", "%1$s assigned system tag %3$s" : "%1$s przypisywalny system etykiet%3$s", diff --git a/apps/updatenotification/l10n/pl.js b/apps/updatenotification/l10n/pl.js index 6551d0808e3..d86fdf3c243 100644 --- a/apps/updatenotification/l10n/pl.js +++ b/apps/updatenotification/l10n/pl.js @@ -1,8 +1,11 @@ OC.L10N.register( "updatenotification", { + "Update notifications" : "Powiadomienia o aktualizacji", "{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.", "Updated channel" : "Zaktualizowano kanał", + "ownCloud core" : "Rdzeń ownCloud", + "Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s", "Updater" : "Aktualizator", "A new version is available: %s" : "Dostępna jest nowa wersja: %s", "Open updater" : "Otwórz aktualizator", diff --git a/apps/updatenotification/l10n/pl.json b/apps/updatenotification/l10n/pl.json index fd859feae11..b5d7132d9f0 100644 --- a/apps/updatenotification/l10n/pl.json +++ b/apps/updatenotification/l10n/pl.json @@ -1,6 +1,9 @@ { "translations": { + "Update notifications" : "Powiadomienia o aktualizacji", "{version} is available. Get more information on how to update." : "Wersja {version} jest dostępna. Dowiedz się jak zaktualizować.", "Updated channel" : "Zaktualizowano kanał", + "ownCloud core" : "Rdzeń ownCloud", + "Update for %1$s to version %2$s is available." : "Jest dostępna aktualizacja dla %1$s do wersji %2$s", "Updater" : "Aktualizator", "A new version is available: %s" : "Dostępna jest nowa wersja: %s", "Open updater" : "Otwórz aktualizator", diff --git a/autotest.sh b/autotest.sh index bd51cddefcf..e798157fe64 100755 --- a/autotest.sh +++ b/autotest.sh @@ -54,7 +54,7 @@ else fi if ! [ -x "$PHPUNIT" ]; then - echo "phpunit executable not found, please install phpunit version >= 3.7" >&2 + echo "phpunit executable not found, please install phpunit version >= 4.4" >&2 exit 3 fi diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php index d060918a506..83c6c1dc168 100644 --- a/core/Command/Encryption/DecryptAll.php +++ b/core/Command/Encryption/DecryptAll.php @@ -129,8 +129,7 @@ class DecryptAll extends Command { } $uid = $input->getArgument('user'); - //FIXME WHEN https://github.com/owncloud/core/issues/24994 is fixed - if ($uid === null) { + if ($uid === '') { $message = 'your ownCloud'; } else { $message = "$uid's account"; diff --git a/core/css/styles.css b/core/css/styles.css index 475c4fa3fb3..451a86a5c47 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -578,9 +578,8 @@ html.ie8 #body-login form input[type="checkbox"] { } /* Fixes for log in page, TODO should be removed some time */ -#body-login .update, -#body-login .error { - margin: 35px auto; +#body-login ul.error-wide { + margin-top: 35px; } #body-login .warning { margin: 0 7px 5px 4px; diff --git a/core/css/tooltip.css b/core/css/tooltip.css index 34d0ec6c70f..af25fd5533d 100644 --- a/core/css/tooltip.css +++ b/core/css/tooltip.css @@ -47,7 +47,7 @@ padding: 0 5px; } .tooltip-inner { - max-width: 200px; + max-width: 350px; padding: 3px 8px; color: #ffffff; text-align: center; diff --git a/core/img/favicon-mask.svg b/core/img/favicon-mask.svg index 1e159f15791..f2984c55027 100644 --- a/core/img/favicon-mask.svg +++ b/core/img/favicon-mask.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="16" viewBox="0 0 16 15.999999" width="16" version="1.1" y="0px" x="0px" enable-background="new 0 0 595.275 311.111"><path style="color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;enable-background:accumulate;text-transform:none;text-decoration-style:solid" d="m8.0115 4.671c-1.5628 0.00015-2.875 1.0702-3.276 2.5097-0.34996-0.76995-1.1202-1.3156-2.0152-1.3157-1.2183 0.000138-2.22 1.0019-2.2201 2.2202-0.000241 1.2186 1.0016 2.2206 2.2201 2.2207 0.8951-0.000109 1.6649-0.5461 2.0148-1.3162 0.4008 1.4398 1.7135 2.51 3.2765 2.5102 1.5542 0.00012 2.86-1.0585 3.2691-2.486 0.35562 0.7558 1.1141 1.2918 1.9988 1.2919 1.2188 0.000215 2.2208-1.0019 2.2206-2.2207-0.000118-1.2186-1.002-2.2204-2.2206-2.2202-0.88475 0.000102-1.6436 0.536-1.9992 1.2919-0.4091-1.4274-1.7144-2.4861-3.2687-2.486zm0 1.3034c1.1736-0.000078 2.1112 0.93725 2.1113 2.111 0.000059 1.1738-0.9375 2.1115-2.1113 2.1114-1.1736-0.000114-2.111-0.9377-2.1108-2.1114 0.000123-1.1736 0.93735-2.1108 2.1108-2.111zm-5.2915 1.194c0.51415 0.000059 0.9168 0.40275 0.91685 0.9169 0.000091 0.51425-0.40262 0.9173-0.91685 0.91735-0.51425-0.00006-0.91695-0.4031-0.91685-0.91735 0.000059-0.51415 0.40273-0.91685 0.91685-0.9169zm10.559 0c0.51425-0.00009 0.91725 0.40264 0.9173 0.9169 0.000122 0.5144-0.40295 0.91745-0.9173 0.91735-0.51425-0.00006-0.91695-0.4031-0.9169-0.91735 0.000059-0.51415 0.40274-0.91685 0.9169-0.9169z"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 595.275 311.111" xml:space="preserve" height="16" width="16" version="1.1" y="0px" x="0px" viewBox="0 0 16 15.999999"><path d="m2.5 0c-1.385 0-2.5 1.115-2.5 2.5v11c0 1.385 1.115 2.5 2.5 2.5h11c1.385 0 2.5-1.115 2.5-2.5v-11c0-1.385-1.115-2.5-2.5-2.5h-11zm5.5117 4.6699c1.5543-0.0001 2.8603 1.0589 3.2693 2.4863 0.356-0.7558 1.114-1.2909 1.998-1.291 1.219-0.0002 2.221 1.0021 2.221 2.2207 0 1.2188-1.002 2.2211-2.221 2.2211-0.884 0-1.642-0.5375-1.998-1.2933-0.409 1.4273-1.7151 2.4863-3.2693 2.4863-1.563 0-2.8765-1.07-3.2773-2.5098-0.3499 0.7701-1.1186 1.3168-2.0137 1.3168-1.2185 0-2.2209-1.0025-2.2207-2.2211 0.0001-1.2183 1.0024-2.2205 2.2207-2.2207 0.895 0.0001 1.6657 0.5465 2.0156 1.3164 0.401-1.4395 1.7126-2.5096 3.2754-2.5097v-0.002zm0 1.3047c-1.1734 0.0002-2.1112 0.9377-2.1113 2.1113-0.0002 1.1737 0.9377 2.1111 2.1113 2.1111 1.1738 0 2.1113-0.9373 2.1113-2.1111 0-1.1737-0.9377-2.1114-2.1113-2.1113zm-5.291 1.1934c-0.5141 0-0.9179 0.4038-0.918 0.9179-0.0001 0.5143 0.4038 0.916 0.918 0.9161 0.5142-0.0001 0.9161-0.4018 0.916-0.9161 0-0.5141-0.4018-0.9179-0.916-0.9179zm10.558 0c-0.514 0-0.918 0.4038-0.918 0.9179 0 0.5143 0.404 0.916 0.918 0.9161 0.515 0.0001 0.918-0.4017 0.918-0.9161 0-0.5142-0.403-0.918-0.918-0.9179z"/></svg> diff --git a/core/img/favicon-touch.png b/core/img/favicon-touch.png Binary files differindex d5d407a0f0d..635806813a6 100644 --- a/core/img/favicon-touch.png +++ b/core/img/favicon-touch.png diff --git a/core/img/favicon-touch.svg b/core/img/favicon-touch.svg index 9b23a7e2212..73f672bc9c0 100644 --- a/core/img/favicon-touch.svg +++ b/core/img/favicon-touch.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="128" viewBox="0 0 128 127.99999" width="128" version="1.1" y="0px" x="0px" enable-background="new 0 0 595.275 311.111"><rect rx="20" ry="20" height="128" width="128" y="-.0000015" x="0" fill="#fff"/><path style="enable-background:accumulate;color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;text-decoration-style:solid;image-rendering:auto;white-space:normal;text-indent:0;text-transform:none" d="m64.091 37.368c-12.502 0.0012-23 8.5614-26.208 20.078-2.7996-6.1595-8.9621-10.525-16.122-10.525-9.7464 0.0011-17.76 8.015-17.761 17.762-0.0019 9.7488 8.0127 17.764 17.761 17.766 7.1608-0.000868 13.319-4.3688 16.119-10.529 3.2064 11.518 13.708 20.08 26.212 20.081 12.434 0.00096 22.881-8.4681 26.153-19.887 2.845 6.0464 8.9128 10.334 15.991 10.335 9.7502 0.0017 17.766-8.0148 17.765-17.766-0.00094-9.7488-8.0163-17.764-17.765-17.762-7.0781 0.00082-13.149 4.288-15.994 10.335-3.274-11.42-13.717-19.889-26.151-19.888zm0 10.427c9.3893-0.000624 16.889 7.4978 16.89 16.888 0.00047 9.3908-7.5 16.892-16.89 16.891-9.3893-0.000912-16.887-7.5015-16.887-16.891 0.000988-9.3886 7.4986-16.887 16.887-16.888zm-42.33 9.552c4.113 0.000472 7.3344 3.222 7.3349 7.3352 0.000728 4.1141-3.221 7.3384-7.3349 7.3389-4.1139-0.00048-7.3356-3.2248-7.3349-7.3389 0.000472-4.1132 3.2218-7.3348 7.3349-7.3352zm84.474 0c4.1138-0.00072 7.338 3.2211 7.3385 7.3352 0.00098 4.115-3.2236 7.3396-7.3385 7.3389-4.114-0.00048-7.3357-3.2248-7.335-7.3389 0.00047-4.1132 3.222-7.3348 7.335-7.3352z" fill="#0082c9"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 595.275 311.111" xml:space="preserve" height="128" width="128" version="1.1" y="0px" x="0px" viewBox="0 0 128 127.99999"><rect rx="20" ry="20" height="128" width="128" y="-.0000015" x="0" fill="#0082c9"/><path style="enable-background:accumulate;color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid" d="m64.091 37.368c-12.502 0.0012-23 8.5614-26.208 20.078-2.7996-6.1595-8.9621-10.525-16.122-10.525-9.7464 0.0011-17.76 8.015-17.761 17.762-0.0019 9.7488 8.0127 17.764 17.761 17.766 7.1608-0.000868 13.319-4.3688 16.119-10.529 3.2064 11.518 13.708 20.08 26.212 20.081 12.434 0.00096 22.881-8.4681 26.153-19.887 2.845 6.0464 8.9128 10.334 15.991 10.335 9.7502 0.0017 17.766-8.0148 17.765-17.766-0.00094-9.7488-8.0163-17.764-17.765-17.762-7.0781 0.00082-13.149 4.288-15.994 10.335-3.274-11.42-13.717-19.889-26.151-19.888zm0 10.427c9.3893-0.000624 16.889 7.4978 16.89 16.888 0.00047 9.3908-7.5 16.892-16.89 16.891-9.3893-0.000912-16.887-7.5015-16.887-16.891 0.000988-9.3886 7.4986-16.887 16.887-16.888zm-42.33 9.552c4.113 0.000472 7.3344 3.222 7.3349 7.3352 0.000728 4.1141-3.221 7.3384-7.3349 7.3389-4.1139-0.00048-7.3356-3.2248-7.3349-7.3389 0.000472-4.1132 3.2218-7.3348 7.3349-7.3352zm84.474 0c4.1138-0.00072 7.338 3.2211 7.3385 7.3352 0.00098 4.115-3.2236 7.3396-7.3385 7.3389-4.114-0.00048-7.3357-3.2248-7.335-7.3389 0.00047-4.1132 3.222-7.3348 7.335-7.3352z" fill="#fff"/></svg> diff --git a/core/img/favicon.ico b/core/img/favicon.ico Binary files differindex 7e18400b4de..cadd9d3471b 100644 --- a/core/img/favicon.ico +++ b/core/img/favicon.ico diff --git a/core/img/favicon.png b/core/img/favicon.png Binary files differindex cc9ba3420fe..3988dce0b41 100644 --- a/core/img/favicon.png +++ b/core/img/favicon.png diff --git a/core/img/favicon.svg b/core/img/favicon.svg index 79d9de34778..2bd731a38c2 100644 --- a/core/img/favicon.svg +++ b/core/img/favicon.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="32" viewBox="0 0 32 31.999997" width="32" version="1.1" y="0px" x="0px" enable-background="new 0 0 595.275 311.111"><rect rx="5" ry="5" height="32" width="32" y="-.0000052588" x="0" fill="#fff"/><path style="enable-background:accumulate;color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;text-decoration-style:solid;image-rendering:auto;white-space:normal;text-indent:0;text-transform:none" d="m16.023 9.342c-3.1256 0.0003-5.7501 2.1404-6.552 5.0194-0.69991-1.5399-2.2405-2.6312-4.0305-2.6314-2.4366 0.000277-4.44 2.0038-4.4403 4.4405-0.00048201 2.4372 2.0032 4.4411 4.4403 4.4414 1.7902-0.000217 3.3298-1.0922 4.0296-2.6323 0.80161 2.8795 3.427 5.02 6.553 5.0203 3.1085 0.00024 5.7201-2.117 6.5383-4.9719 0.71125 1.5116 2.2282 2.5836 3.9976 2.5838 2.4376 0.000431 4.4416-2.0037 4.4412-4.4414-0.000235-2.4372-2.0041-4.4409-4.4412-4.4405-1.7695 0.000205-3.2873 1.072-3.9985 2.5838-0.8182-2.8548-3.4289-4.9721-6.5374-4.9719zm0 2.6067c2.3473-0.000156 4.2224 1.8745 4.2226 4.2219 0.000118 2.3477-1.875 4.223-4.2226 4.2228-2.3473-0.000228-4.2219-1.8754-4.2217-4.2228 0.000247-2.3471 1.8747-4.2216 4.2217-4.2219zm-10.583 2.388c1.0283 0.000118 1.8336 0.8055 1.8337 1.8338 0.000182 1.0285-0.80524 1.8346-1.8337 1.8347-1.0285-0.00012-1.8339-0.8062-1.8337-1.8347 0.000118-1.0283 0.80546-1.8337 1.8337-1.8338zm21.119 0c1.0285-0.00018 1.8345 0.80527 1.8346 1.8338 0.000245 1.0288-0.8059 1.8349-1.8346 1.8347-1.0285-0.00012-1.8339-0.8062-1.8338-1.8347 0.000118-1.0283 0.80549-1.8337 1.8338-1.8338z" fill="#0082c9"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 595.275 311.111" xml:space="preserve" height="32" width="32" version="1.1" y="0px" x="0px" viewBox="0 0 32 31.999997"><rect rx="5" ry="5" height="32" width="32" y="-.0000052588" x="0" fill="#0082c9"/><path style="enable-background:accumulate;color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid" d="m16.023 9.342c-3.1256 0.0003-5.7501 2.1404-6.552 5.0194-0.69991-1.5399-2.2405-2.6312-4.0305-2.6314-2.4366 0.000277-4.44 2.0038-4.4403 4.4405-0.00048201 2.4372 2.0032 4.4411 4.4403 4.4414 1.7902-0.000217 3.3298-1.0922 4.0296-2.6323 0.80161 2.8795 3.427 5.02 6.553 5.0203 3.1085 0.00024 5.7201-2.117 6.5383-4.9719 0.71125 1.5116 2.2282 2.5836 3.9976 2.5838 2.4376 0.000431 4.4416-2.0037 4.4412-4.4414-0.000235-2.4372-2.0041-4.4409-4.4412-4.4405-1.7695 0.000205-3.2873 1.072-3.9985 2.5838-0.8182-2.8548-3.4289-4.9721-6.5374-4.9719zm0 2.6067c2.3473-0.000156 4.2224 1.8745 4.2226 4.2219 0.000118 2.3477-1.875 4.223-4.2226 4.2228-2.3473-0.000228-4.2219-1.8754-4.2217-4.2228 0.000247-2.3471 1.8747-4.2216 4.2217-4.2219zm-10.583 2.388c1.0283 0.000118 1.8336 0.8055 1.8337 1.8338 0.000182 1.0285-0.80524 1.8346-1.8337 1.8347-1.0285-0.00012-1.8339-0.8062-1.8337-1.8347 0.000118-1.0283 0.80546-1.8337 1.8337-1.8338zm21.119 0c1.0285-0.00018 1.8345 0.80527 1.8346 1.8338 0.000245 1.0288-0.8059 1.8349-1.8346 1.8347-1.0285-0.00012-1.8339-0.8062-1.8338-1.8347 0.000118-1.0283 0.80549-1.8337 1.8338-1.8338z" fill="#fff"/></svg> diff --git a/core/js/setupchecks.js b/core/js/setupchecks.js index 4cc50e51ae6..f987c9f04e6 100644 --- a/core/js/setupchecks.js +++ b/core/js/setupchecks.js @@ -197,7 +197,7 @@ } var afterCall = function(xhr) { var messages = []; - if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301 && xhr.responseText === '') { + if (xhr.status !== 403 && xhr.status !== 307 && xhr.status !== 301 && xhr.responseText !== '') { messages.push({ msg: t('core', 'Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root.'), type: OC.SetupChecks.MESSAGE_TYPE_ERROR @@ -208,7 +208,7 @@ $.ajax({ type: 'GET', - url: OC.linkTo('', oc_dataURL+'/.ocdata'), + url: OC.linkTo('', oc_dataURL+'/htaccesstest.txt?t=' + (new Date()).getTime()), complete: afterCall }); return deferred.promise(); diff --git a/core/js/tests/specs/setupchecksSpec.js b/core/js/tests/specs/setupchecksSpec.js index 4931ca990da..172e6e27135 100644 --- a/core/js/tests/specs/setupchecksSpec.js +++ b/core/js/tests/specs/setupchecksSpec.js @@ -103,7 +103,7 @@ describe('OC.SetupChecks tests', function() { it('should return an error if data directory is not protected', function(done) { var async = OC.SetupChecks.checkDataProtected(); - suite.server.requests[0].respond(200); + suite.server.requests[0].respond(200, {'Content-Type': 'text/plain'}, 'file contents'); async.done(function( data, s, x ){ expect(data).toEqual([ diff --git a/core/l10n/ja.js b/core/l10n/ja.js index 397a417eb9d..a45c8620c6e 100644 --- a/core/l10n/ja.js +++ b/core/l10n/ja.js @@ -295,6 +295,7 @@ OC.L10N.register( "This means only administrators can use the instance." : "これは、管理者のみがインスタンスを利用できることを意味しています。", "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", + "Two-step verification" : "2段階認証", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", diff --git a/core/l10n/ja.json b/core/l10n/ja.json index 11c88968ee2..b5e9ba9b9d0 100644 --- a/core/l10n/ja.json +++ b/core/l10n/ja.json @@ -293,6 +293,7 @@ "This means only administrators can use the instance." : "これは、管理者のみがインスタンスを利用できることを意味しています。", "Contact your system administrator if this message persists or appeared unexpectedly." : "このメッセージが引き続きもしくは予期せず現れる場合は、システム管理者に問い合わせてください。", "Thank you for your patience." : "しばらくお待ちください。", + "Two-step verification" : "2段階認証", "You are accessing the server from an untrusted domain." : "信頼されていないドメインからサーバーにアクセスしています。", "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "管理者に問い合わせてください。このサーバーの管理者の場合は、\"trusted_domain\" の設定を config/config.php に設定してください。config/config.sample.php にサンプルの設定方法が記載してあります。", "Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "環境により、下のボタンで信頼するドメインに追加する必要があるかもしれません。", diff --git a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php index 2b9a072e59a..d84e9963436 100644 --- a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php @@ -26,13 +26,13 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Middleware\Security\Exceptions\SecurityException; use OC\AppFramework\Utility\ControllerMethodReflector; +use OC\User\Session; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; -use OCP\IRequest; -use OCP\IUserSession; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Middleware; +use OCP\IRequest; /** * This middleware sets the correct CORS headers on a response if the @@ -53,18 +53,18 @@ class CORSMiddleware extends Middleware { private $reflector; /** - * @var IUserSession + * @var Session */ private $session; /** * @param IRequest $request * @param ControllerMethodReflector $reflector - * @param IUserSession $session + * @param Session $session */ public function __construct(IRequest $request, ControllerMethodReflector $reflector, - IUserSession $session) { + Session $session) { $this->request = $request; $this->reflector = $reflector; $this->session = $session; @@ -89,7 +89,7 @@ class CORSMiddleware extends Middleware { $pass = $this->request->server['PHP_AUTH_PW']; $this->session->logout(); - if(!$this->session->login($user, $pass)) { + if(!$this->session->logClientIn($user, $pass)) { throw new SecurityException('CORS requires basic auth', Http::STATUS_UNAUTHORIZED); } } diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php index 9b55c312e26..8beba116fe1 100644 --- a/lib/private/Files/Utils/Scanner.php +++ b/lib/private/Files/Utils/Scanner.php @@ -160,7 +160,12 @@ class Scanner extends PublicEmitter { if ($storage->instanceOfStorage('\OC\Files\Storage\Home') and (!$storage->isCreatable('') or !$storage->isCreatable('files')) ) { - throw new ForbiddenException(); + if ($storage->file_exists('') or $storage->getCache()->inCache('')) { + throw new ForbiddenException(); + } else {// if the root exists in neither the cache nor the storage the user isn't setup yet + break; + } + } $relativePath = $mount->getInternalPath($dir); $scanner = $storage->getScanner(); diff --git a/lib/private/Log.php b/lib/private/Log.php index 6028064a878..49223521916 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -60,6 +60,32 @@ class Log implements ILogger { /** @var Normalizer */ private $normalizer; + protected $methodsWithSensitiveParameters = [ + // Session/User + 'login', + 'checkPassword', + 'updatePrivateKeyPassword', + 'validateUserPass', + + // TokenProvider + 'getToken', + 'isTokenPassword', + 'getPassword', + 'decryptPassword', + 'logClientIn', + 'generateToken', + 'validateToken', + + // TwoFactorAuth + 'solveChallenge', + 'verifyChallenge', + + //ICrypto + 'calculateHMAC', + 'encrypt', + 'decrypt', + ]; + /** * @param string $logger The logger that should be used * @param SystemConfig $config the system config object @@ -286,7 +312,7 @@ class Log implements ILogger { 'File' => $exception->getFile(), 'Line' => $exception->getLine(), ); - $exception['Trace'] = preg_replace('!(login|checkPassword|updatePrivateKeyPassword|validateUserPass)\(.*\)!', '$1(*** username and password replaced ***)', $exception['Trace']); + $exception['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $exception['Trace']); $msg = isset($context['message']) ? $context['message'] : 'Exception'; $msg .= ': ' . json_encode($exception); $this->error($msg, $context); diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 362468d4109..f560bb4bfc0 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -361,7 +361,14 @@ class Session implements IUserSession, Emitter { // TODO: throw LoginException instead (https://github.com/owncloud/core/pull/24616) return false; } - return $this->login($user, $password); + if (!$this->login($user, $password) ) { + $users = $this->manager->getByEmail($user); + if (count($users) === 1) { + return $this->login($users[0]->getUID(), $password); + } + return false; + } + return true; } private function isTokenAuthEnforced() { @@ -376,7 +383,11 @@ class Session implements IUserSession, Emitter { ); $user = $this->manager->get($username); if (is_null($user)) { - return true; + $users = $this->manager->getByEmail($username); + if (count($users) !== 1) { + return true; + } + $user = $users[0]; } // DI not possible due to cyclic dependencies :'-/ return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user); @@ -385,7 +396,7 @@ class Session implements IUserSession, Emitter { /** * Check if the given 'password' is actually a device token * - * @param type $password + * @param string $password * @return boolean */ public function isTokenPassword($password) { @@ -470,11 +481,39 @@ class Session implements IUserSession, Emitter { $name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser'; try { $sessionId = $this->session->getId(); - $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $password, $name); + $pwd = $this->getPassword($password); + $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name); + return true; } catch (SessionNotAvailableException $ex) { + // This can happen with OCC, where a memory session is used + // if a memory session is used, we shouldn't create a session token anyway + return false; + } + } + /** + * Checks if the given password is a token. + * If yes, the password is extracted from the token. + * If no, the same password is returned. + * + * @param string $password either the login password or a device token + * @return string|null the password or null if none was set in the token + */ + private function getPassword($password) { + if (is_null($password)) { + // This is surely no token ;-) + return null; + } + try { + $token = $this->tokenProvider->getToken($password); + try { + return $this->tokenProvider->getPassword($token, $password); + } catch (PasswordlessTokenException $ex) { + return null; + } + } catch (InvalidTokenException $ex) { + return $password; } - return true; } /** diff --git a/lib/private/legacy/api.php b/lib/private/legacy/api.php index 1e581153ce6..024f3c0fb63 100644 --- a/lib/private/legacy/api.php +++ b/lib/private/legacy/api.php @@ -349,7 +349,7 @@ class OC_API { if ($ocsApiRequest) { // initialize the user's filesystem - \OC_Util::setUpFS(\OC_User::getUser()); + \OC_Util::setupFS(\OC_User::getUser()); self::$isLoggedIn = true; return OC_User::getUser(); @@ -374,7 +374,7 @@ class OC_API { self::$logoutRequired = true; // initialize the user's filesystem - \OC_Util::setUpFS(\OC_User::getUser()); + \OC_Util::setupFS(\OC_User::getUser()); self::$isLoggedIn = true; return \OC_User::getUser(); diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index b744db21238..a863348566e 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -1128,19 +1128,8 @@ class OC_Util { return $encoded; } - /** - * Check if the .htaccess file is working - * @param \OCP\IConfig $config - * @return bool - * @throws Exception - * @throws \OC\HintException If the test file can't get written. - */ - public function isHtaccessWorking(\OCP\IConfig $config) { - - if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) { - return true; - } + public function createHtaccessTestFile(\OCP\IConfig $config) { // php dev server does not support htaccess if (php_sapi_name() === 'cli-server') { return false; @@ -1148,7 +1137,7 @@ class OC_Util { // testdata $fileName = '/htaccesstest.txt'; - $testContent = 'testcontent'; + $testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.'; // creating a test file $testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName; @@ -1164,6 +1153,28 @@ class OC_Util { } fwrite($fp, $testContent); fclose($fp); + } + + /** + * Check if the .htaccess file is working + * @param \OCP\IConfig $config + * @return bool + * @throws Exception + * @throws \OC\HintException If the test file can't get written. + */ + public function isHtaccessWorking(\OCP\IConfig $config) { + + if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) { + return true; + } + + $testContent = $this->createHtaccessTestFile($config); + if ($testContent === false) { + return false; + } + + $fileName = '/htaccesstest.txt'; + $testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName; // accessing the file via http $url = \OC::$server->getURLGenerator()->getAbsoluteURL(OC::$WEBROOT . '/data' . $fileName); diff --git a/settings/admin.php b/settings/admin.php index 6fb65b013e6..3ae7455b2ea 100644 --- a/settings/admin.php +++ b/settings/admin.php @@ -267,3 +267,7 @@ if ($updaterAppPanel) { $template->assign('forms', $formsAndMore); $template->printPage(); + +$util = new \OC_Util(); +$util->createHtaccessTestFile(\OC::$server->getConfig()); + diff --git a/settings/js/log.js b/settings/js/log.js index 43ef561f7ee..a1ad29d72e7 100644 --- a/settings/js/log.js +++ b/settings/js/log.js @@ -64,6 +64,11 @@ OC.Log = { timeTd.text(formatDate(entry.time * 1000)); } row.append(timeTd); + + var userTd = $('<td/>'); + userTd.text(entry.user); + row.append(userTd); + $('#log').append(row); } OC.Log.loaded += entries.length; diff --git a/settings/l10n/pl.js b/settings/l10n/pl.js index 8c592ec5114..7f14e552192 100644 --- a/settings/l10n/pl.js +++ b/settings/l10n/pl.js @@ -6,6 +6,7 @@ OC.L10N.register( "Authentication error" : "Błąd uwierzytelniania", "Please provide an admin recovery password, otherwise all user data will be lost" : "Podaj hasło odzyskiwania administratora, w przeciwnym razie wszystkie dane użytkownika zostaną utracone", "Wrong admin recovery password. Please check the password and try again." : "Błędne hasło odzyskiwania. Sprawdź hasło i spróbuj ponownie.", + "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Zaplecze nie obsługuje zmiany hasła, ale klucz szyfrowania użytkownika został pomyślnie zaktualizowany.", "Unable to change password" : "Nie można zmienić hasła", "Enabled" : "Włączone", "Not enabled" : "Nie włączone", diff --git a/settings/l10n/pl.json b/settings/l10n/pl.json index ded5e82af0a..6ab582825f7 100644 --- a/settings/l10n/pl.json +++ b/settings/l10n/pl.json @@ -4,6 +4,7 @@ "Authentication error" : "Błąd uwierzytelniania", "Please provide an admin recovery password, otherwise all user data will be lost" : "Podaj hasło odzyskiwania administratora, w przeciwnym razie wszystkie dane użytkownika zostaną utracone", "Wrong admin recovery password. Please check the password and try again." : "Błędne hasło odzyskiwania. Sprawdź hasło i spróbuj ponownie.", + "Backend doesn't support password change, but the user's encryption key was successfully updated." : "Zaplecze nie obsługuje zmiany hasła, ale klucz szyfrowania użytkownika został pomyślnie zaktualizowany.", "Unable to change password" : "Nie można zmienić hasła", "Enabled" : "Włączone", "Not enabled" : "Nie włączone", diff --git a/settings/l10n/ro.js b/settings/l10n/ro.js index 4f965ce5b74..8afe595859a 100644 --- a/settings/l10n/ro.js +++ b/settings/l10n/ro.js @@ -48,8 +48,16 @@ OC.L10N.register( "Unable to add user to group %s" : "Nu s-a putut adăuga utilizatorul în grupul %s", "Unable to remove user from group %s" : "Nu s-a putut elimina utilizatorul din grupul %s", "Couldn't update app." : "Aplicaţia nu s-a putut actualiza.", + "Add trusted domain" : "Adaugă domeniu de încredere", + "Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată", + "Migration started …" : "Migrarea a început...", "Sending..." : "Se expediază...", + "Official" : "Oficial", + "Approved" : "Aprobat", + "Experimental" : "Experimental", "All" : "Toate ", + "No apps found for your version" : "Nu au fost găsite aplicații pentru versiunea ta", + "The app will be downloaded from the app store" : "Aplicația va fi descărcată din magazin", "Please wait...." : "Aşteptaţi vă rog....", "Error while disabling app" : "Eroare în timpul dezactivării aplicației", "Disable" : "Dezactivați", @@ -60,7 +68,9 @@ OC.L10N.register( "Updated" : "Actualizat", "Uninstalling ...." : "Dezinstalaza ....", "Uninstall" : "Dezinstalați", + "Valid until {date}" : "Valabil până la {date}", "Delete" : "Șterge", + "An error occurred: {message}" : "A apărut o eroare: {message}", "Select a profile picture" : "Selectează o imagine de profil", "Very weak password" : "Parolă foarte slabă", "Weak password" : "Parolă slabă", @@ -68,13 +78,21 @@ OC.L10N.register( "Good password" : "Parolă bună", "Strong password" : "Parolă puternică", "Groups" : "Grupuri", + "Unable to delete {objName}" : "Nu s-a putut șterge {objName}", + "deleted {groupName}" : "{groupName} s-a șters", "undo" : "Anulează ultima acțiune", + "no group" : "niciun grup", "never" : "niciodată", + "deleted {userName}" : "{userName} șters", "add group" : "adăugaţi grupul", "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid", "A valid password must be provided" : "Trebuie să furnizaţi o parolă validă", "__language_name__" : "_language_name_", "Unlimited" : "Nelimitată", + "Personal info" : "Informații personale", + "Sessions" : "Sesiuni", + "Devices" : "Dispozitive", + "Sync clients" : "Sincronizează clienții", "None" : "Niciuna", "Login" : "Autentificare", "SSL" : "SSL", @@ -83,31 +101,75 @@ OC.L10N.register( "Open documentation" : "Deschide documentația", "Allow apps to use the Share API" : "Permite aplicațiilor să folosească API-ul de partajare", "Allow public uploads" : "Permite încărcări publice", + "Enforce password protection" : "Impune protecția prin parolă", + "Set default expiration date" : "Setează data implicită de expirare", "Allow users to send mail notification for shared files" : "Permite utilizatorilor sa expedieze notificări prin e-mail pentru dosarele comune", + "Expire after " : "Expiră după", "days" : "zile", + "Enforce expiration date" : "Impune data de expirare", "Allow resharing" : "Permite repartajarea", + "Allow sharing with groups" : "Permite partajarea cu grupuri", + "Exclude groups from sharing" : "Exclude grupuri de la partajare", "Execute one task with each page loaded" : "Execută o sarcină la fiecare pagină încărcată", + "Enable server-side encryption" : "Activează criptarea pe server", + "Please read carefully before activating server-side encryption: " : "Citește cu atenție înainte să activezi criptarea pe server:", + "This is the final warning: Do you really want to enable encryption?" : "Aceasta este avertizarea finală: Chiar vrei să activezi criptarea?", "Enable encryption" : "Activează criptarea", + "Select default encryption module:" : "Selectează modulul implicit de criptare:", + "Start migration" : "Pornește migrarea", "Send mode" : "Modul de expediere", "Encryption" : "Încriptare", + "From address" : "De la adresa", + "mail" : "poștă", "Authentication method" : "Modul de autentificare", "Authentication required" : "Autentificare necesară", "Server address" : "Adresa server-ului", "Port" : "Portul", + "Credentials" : "Detalii de autentificare", "SMTP Username" : "Nume utilizator SMTP", "SMTP Password" : "Parolă SMTP", + "Store credentials" : "Stochează datele de autentificare", "Test email settings" : "Verifică setările de e-mail", "Send email" : "Expediază mesajul", + "Download logfile" : "Descarcă fișierul cu loguri", "More" : "Mai mult", "Less" : "Mai puțin", + "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Fișierul cu loguri este mai mare de 100 MB. Descărcarea acestuia ar putea dura ceva timp!", + "What to log" : "Ce să loghezi", + "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite e folosit ca o bază de date. Pentru instalări mari recomandăm folosirea unei alte baze de date.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "În special atunci când este folosit clientul desktop pentru sincronizarea fișierelor, utilizarea SQLite este nerecomandată.", + "How to do backups" : "Cum să faci copii de rezervă", + "Advanced monitoring" : "Monitorizare avansată", "Version" : "Versiunea", + "Developer documentation" : "Documentație pentru dezvoltatori", + "by %s" : "de %s", + "%s-licensed" : "%s-licențiat", + "Documentation:" : "Documentație:", + "User documentation" : "Documentație utilizator", + "Admin documentation" : "Documentație pentru administrare", + "Show description …" : "Arată descriere ...", + "Hide description …" : "Ascunde descriere ...", + "This app has an update available." : "Este disponibilă o actualizare pentru această aplicație.", + "Enable only for specific groups" : "Activează doar pentru grupuri specifice", + "Uninstall App" : "Dezinstalează aplicația", + "Enable experimental apps" : "Activează aplicațiile experimentale", + "SSL Root Certificates" : "Certificate SSL rădăcină", + "Common Name" : "Nume comun", + "Valid until" : "Valabil până la", + "Issued By" : "Emis de", + "Valid until %s" : "Valabil până la %s", + "Import root certificate" : "Importă certificat rădăcină", "Cheers!" : "Noroc!", + "Administrator documentation" : "Documentație pentru administrare", + "Online documentation" : "Documentație online", "Forum" : "Forum", + "Commercial support" : "Suport comercial", "Profile picture" : "Imagine de profil", "Upload new" : "Încarcă una nouă", "Remove image" : "Înlătură imagine", + "png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB", "Cancel" : "Anulare", + "Full name" : "Nume complet", "Email" : "Email", "Your email address" : "Adresa ta de email", "Password" : "Parolă", @@ -115,6 +177,8 @@ OC.L10N.register( "Current password" : "Parola curentă", "New password" : "Noua parolă", "Change password" : "Schimbă parola", + "Most recent activity" : "Cea mai recentă activitate", + "You've linked these devices." : "Ai legat aceste dispozitive.", "Name" : "Nume", "Language" : "Limba", "Help translate" : "Ajută la traducere", @@ -128,12 +192,16 @@ OC.L10N.register( "Admin Recovery Password" : "Parolă de recuperare a Administratorului", "Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei", "Group" : "Grup", + "Admins" : "Administratori", "Default Quota" : "Cotă implicită", "Other" : "Altele", "Full Name" : "Nume complet", + "Group Admin for" : "Administrator de grup pentru", "Quota" : "Cotă", + "Last Login" : "Ultima autentificare", "change full name" : "schimbă numele complet", "set new password" : "setează parolă nouă", + "change email address" : "schimbă adresa email", "Default" : "Implicită" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/settings/l10n/ro.json b/settings/l10n/ro.json index 05540e9da90..8682709a39e 100644 --- a/settings/l10n/ro.json +++ b/settings/l10n/ro.json @@ -46,8 +46,16 @@ "Unable to add user to group %s" : "Nu s-a putut adăuga utilizatorul în grupul %s", "Unable to remove user from group %s" : "Nu s-a putut elimina utilizatorul din grupul %s", "Couldn't update app." : "Aplicaţia nu s-a putut actualiza.", + "Add trusted domain" : "Adaugă domeniu de încredere", + "Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată", + "Migration started …" : "Migrarea a început...", "Sending..." : "Se expediază...", + "Official" : "Oficial", + "Approved" : "Aprobat", + "Experimental" : "Experimental", "All" : "Toate ", + "No apps found for your version" : "Nu au fost găsite aplicații pentru versiunea ta", + "The app will be downloaded from the app store" : "Aplicația va fi descărcată din magazin", "Please wait...." : "Aşteptaţi vă rog....", "Error while disabling app" : "Eroare în timpul dezactivării aplicației", "Disable" : "Dezactivați", @@ -58,7 +66,9 @@ "Updated" : "Actualizat", "Uninstalling ...." : "Dezinstalaza ....", "Uninstall" : "Dezinstalați", + "Valid until {date}" : "Valabil până la {date}", "Delete" : "Șterge", + "An error occurred: {message}" : "A apărut o eroare: {message}", "Select a profile picture" : "Selectează o imagine de profil", "Very weak password" : "Parolă foarte slabă", "Weak password" : "Parolă slabă", @@ -66,13 +76,21 @@ "Good password" : "Parolă bună", "Strong password" : "Parolă puternică", "Groups" : "Grupuri", + "Unable to delete {objName}" : "Nu s-a putut șterge {objName}", + "deleted {groupName}" : "{groupName} s-a șters", "undo" : "Anulează ultima acțiune", + "no group" : "niciun grup", "never" : "niciodată", + "deleted {userName}" : "{userName} șters", "add group" : "adăugaţi grupul", "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid", "A valid password must be provided" : "Trebuie să furnizaţi o parolă validă", "__language_name__" : "_language_name_", "Unlimited" : "Nelimitată", + "Personal info" : "Informații personale", + "Sessions" : "Sesiuni", + "Devices" : "Dispozitive", + "Sync clients" : "Sincronizează clienții", "None" : "Niciuna", "Login" : "Autentificare", "SSL" : "SSL", @@ -81,31 +99,75 @@ "Open documentation" : "Deschide documentația", "Allow apps to use the Share API" : "Permite aplicațiilor să folosească API-ul de partajare", "Allow public uploads" : "Permite încărcări publice", + "Enforce password protection" : "Impune protecția prin parolă", + "Set default expiration date" : "Setează data implicită de expirare", "Allow users to send mail notification for shared files" : "Permite utilizatorilor sa expedieze notificări prin e-mail pentru dosarele comune", + "Expire after " : "Expiră după", "days" : "zile", + "Enforce expiration date" : "Impune data de expirare", "Allow resharing" : "Permite repartajarea", + "Allow sharing with groups" : "Permite partajarea cu grupuri", + "Exclude groups from sharing" : "Exclude grupuri de la partajare", "Execute one task with each page loaded" : "Execută o sarcină la fiecare pagină încărcată", + "Enable server-side encryption" : "Activează criptarea pe server", + "Please read carefully before activating server-side encryption: " : "Citește cu atenție înainte să activezi criptarea pe server:", + "This is the final warning: Do you really want to enable encryption?" : "Aceasta este avertizarea finală: Chiar vrei să activezi criptarea?", "Enable encryption" : "Activează criptarea", + "Select default encryption module:" : "Selectează modulul implicit de criptare:", + "Start migration" : "Pornește migrarea", "Send mode" : "Modul de expediere", "Encryption" : "Încriptare", + "From address" : "De la adresa", + "mail" : "poștă", "Authentication method" : "Modul de autentificare", "Authentication required" : "Autentificare necesară", "Server address" : "Adresa server-ului", "Port" : "Portul", + "Credentials" : "Detalii de autentificare", "SMTP Username" : "Nume utilizator SMTP", "SMTP Password" : "Parolă SMTP", + "Store credentials" : "Stochează datele de autentificare", "Test email settings" : "Verifică setările de e-mail", "Send email" : "Expediază mesajul", + "Download logfile" : "Descarcă fișierul cu loguri", "More" : "Mai mult", "Less" : "Mai puțin", + "The logfile is bigger than 100 MB. Downloading it may take some time!" : "Fișierul cu loguri este mai mare de 100 MB. Descărcarea acestuia ar putea dura ceva timp!", + "What to log" : "Ce să loghezi", + "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite e folosit ca o bază de date. Pentru instalări mari recomandăm folosirea unei alte baze de date.", "Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "În special atunci când este folosit clientul desktop pentru sincronizarea fișierelor, utilizarea SQLite este nerecomandată.", + "How to do backups" : "Cum să faci copii de rezervă", + "Advanced monitoring" : "Monitorizare avansată", "Version" : "Versiunea", + "Developer documentation" : "Documentație pentru dezvoltatori", + "by %s" : "de %s", + "%s-licensed" : "%s-licențiat", + "Documentation:" : "Documentație:", + "User documentation" : "Documentație utilizator", + "Admin documentation" : "Documentație pentru administrare", + "Show description …" : "Arată descriere ...", + "Hide description …" : "Ascunde descriere ...", + "This app has an update available." : "Este disponibilă o actualizare pentru această aplicație.", + "Enable only for specific groups" : "Activează doar pentru grupuri specifice", + "Uninstall App" : "Dezinstalează aplicația", + "Enable experimental apps" : "Activează aplicațiile experimentale", + "SSL Root Certificates" : "Certificate SSL rădăcină", + "Common Name" : "Nume comun", + "Valid until" : "Valabil până la", + "Issued By" : "Emis de", + "Valid until %s" : "Valabil până la %s", + "Import root certificate" : "Importă certificat rădăcină", "Cheers!" : "Noroc!", + "Administrator documentation" : "Documentație pentru administrare", + "Online documentation" : "Documentație online", "Forum" : "Forum", + "Commercial support" : "Suport comercial", "Profile picture" : "Imagine de profil", "Upload new" : "Încarcă una nouă", "Remove image" : "Înlătură imagine", + "png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB", "Cancel" : "Anulare", + "Full name" : "Nume complet", "Email" : "Email", "Your email address" : "Adresa ta de email", "Password" : "Parolă", @@ -113,6 +175,8 @@ "Current password" : "Parola curentă", "New password" : "Noua parolă", "Change password" : "Schimbă parola", + "Most recent activity" : "Cea mai recentă activitate", + "You've linked these devices." : "Ai legat aceste dispozitive.", "Name" : "Nume", "Language" : "Limba", "Help translate" : "Ajută la traducere", @@ -126,12 +190,16 @@ "Admin Recovery Password" : "Parolă de recuperare a Administratorului", "Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei", "Group" : "Grup", + "Admins" : "Administratori", "Default Quota" : "Cotă implicită", "Other" : "Altele", "Full Name" : "Nume complet", + "Group Admin for" : "Administrator de grup pentru", "Quota" : "Cotă", + "Last Login" : "Ultima autentificare", "change full name" : "schimbă numele complet", "set new password" : "setează parolă nouă", + "change email address" : "schimbă adresa email", "Default" : "Implicită" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 0cdefe10083..b5c5b2510b6 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -519,6 +519,7 @@ if ($_['cronErrors']) { p($entry->time); }?> </td> + <td><?php isset($entry->user) ? p($entry->user) : p('--') ?></td> </tr> <?php endforeach;?> </table> diff --git a/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php b/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php index 8e53c9202cf..a398dc2320c 100644 --- a/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php +++ b/tests/lib/AppFramework/Middleware/Security/CORSMiddlewareTest.php @@ -16,7 +16,6 @@ use OC\AppFramework\Http\Request; use OC\AppFramework\Middleware\Security\CORSMiddleware; use OC\AppFramework\Utility\ControllerMethodReflector; use OC\AppFramework\Middleware\Security\Exceptions\SecurityException; -use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\Response; @@ -29,7 +28,9 @@ class CORSMiddlewareTest extends \Test\TestCase { protected function setUp() { parent::setUp(); $this->reflector = new ControllerMethodReflector(); - $this->session = $this->getMock('\OCP\IUserSession'); + $this->session = $this->getMockBuilder('\OC\User\Session') + ->disableOriginalConstructor() + ->getMock(); } /** @@ -127,7 +128,7 @@ class CORSMiddlewareTest extends \Test\TestCase { $this->session->expects($this->never()) ->method('logout'); $this->session->expects($this->never()) - ->method('login') + ->method('logClientIn') ->with($this->equalTo('user'), $this->equalTo('pass')) ->will($this->returnValue(true)); $this->reflector->reflect($this, __FUNCTION__); @@ -150,7 +151,7 @@ class CORSMiddlewareTest extends \Test\TestCase { $this->session->expects($this->once()) ->method('logout'); $this->session->expects($this->once()) - ->method('login') + ->method('logClientIn') ->with($this->equalTo('user'), $this->equalTo('pass')) ->will($this->returnValue(true)); $this->reflector->reflect($this, __FUNCTION__); @@ -175,7 +176,7 @@ class CORSMiddlewareTest extends \Test\TestCase { $this->session->expects($this->once()) ->method('logout'); $this->session->expects($this->once()) - ->method('login') + ->method('logClientIn') ->with($this->equalTo('user'), $this->equalTo('pass')) ->will($this->returnValue(false)); $this->reflector->reflect($this, __FUNCTION__); diff --git a/tests/lib/LoggerTest.php b/tests/lib/LoggerTest.php index 4eb04b00f58..4b80c01f343 100644 --- a/tests/lib/LoggerTest.php +++ b/tests/lib/LoggerTest.php @@ -89,7 +89,7 @@ class LoggerTest extends TestCase { foreach($logLines as $logLine) { $this->assertNotContains($user, $logLine); $this->assertNotContains($password, $logLine); - $this->assertContains('login(*** username and password replaced ***)', $logLine); + $this->assertContains('login(*** sensitive parameters replaced ***)', $logLine); } } @@ -104,7 +104,7 @@ class LoggerTest extends TestCase { foreach($logLines as $logLine) { $this->assertNotContains($user, $logLine); $this->assertNotContains($password, $logLine); - $this->assertContains('checkPassword(*** username and password replaced ***)', $logLine); + $this->assertContains('checkPassword(*** sensitive parameters replaced ***)', $logLine); } } @@ -119,7 +119,7 @@ class LoggerTest extends TestCase { foreach($logLines as $logLine) { $this->assertNotContains($user, $logLine); $this->assertNotContains($password, $logLine); - $this->assertContains('validateUserPass(*** username and password replaced ***)', $logLine); + $this->assertContains('validateUserPass(*** sensitive parameters replaced ***)', $logLine); } } } diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index 36f14e85492..eac38ebba16 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -22,7 +22,7 @@ class SessionTest extends \Test\TestCase { private $timeFactory; /** @var \OC\Authentication\Token\DefaultTokenProvider */ - protected $defaultProvider; + protected $tokenProvider; /** @var \OCP\IConfig */ private $config; @@ -34,9 +34,7 @@ class SessionTest extends \Test\TestCase { $this->timeFactory->expects($this->any()) ->method('getTime') ->will($this->returnValue(10000)); - $this->defaultProvider = $this->getMockBuilder('\OC\Authentication\Token\DefaultTokenProvider') - ->disableOriginalConstructor() - ->getMock(); + $this->tokenProvider = $this->getMock('\OC\Authentication\Token\IProvider'); $this->config = $this->getMock('\OCP\IConfig'); } @@ -61,14 +59,14 @@ class SessionTest extends \Test\TestCase { $session->expects($this->once()) ->method('getId') ->will($this->returnValue($sessionId)); - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('getToken') ->will($this->returnValue($token)); $session->expects($this->at(2)) ->method('get') ->with('last_login_check') ->will($this->returnValue(null)); // No check has been run yet - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('getPassword') ->with($token, $sessionId) ->will($this->returnValue('password123')); @@ -87,7 +85,7 @@ class SessionTest extends \Test\TestCase { ->method('get') ->with('last_token_update') ->will($this->returnValue(null)); // No check run so far - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('updateToken') ->with($token); $session->expects($this->at(5)) @@ -99,7 +97,7 @@ class SessionTest extends \Test\TestCase { ->with($expectedUser->getUID()) ->will($this->returnValue($expectedUser)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $user = $userSession->getUser(); $this->assertSame($expectedUser, $user); } @@ -122,7 +120,7 @@ class SessionTest extends \Test\TestCase { ->getMock(); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) ->setMethods([ 'getUser' ]) @@ -149,7 +147,7 @@ class SessionTest extends \Test\TestCase { ->method('getUID') ->will($this->returnValue('foo')); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $userSession->setUser($user); } @@ -201,7 +199,7 @@ class SessionTest extends \Test\TestCase { ->will($this->returnValue($user)); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) ->setMethods([ 'prepareUserLogin' ]) @@ -248,7 +246,7 @@ class SessionTest extends \Test\TestCase { ->with('foo', 'bar') ->will($this->returnValue($user)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $userSession->login('foo', 'bar'); } @@ -284,7 +282,7 @@ class SessionTest extends \Test\TestCase { ->with('foo', 'bar') ->will($this->returnValue(false)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $userSession->login('foo', 'bar'); } @@ -304,7 +302,7 @@ class SessionTest extends \Test\TestCase { ->with('foo', 'bar') ->will($this->returnValue(false)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $userSession->login('foo', 'bar'); } @@ -316,11 +314,11 @@ class SessionTest extends \Test\TestCase { /** @var \OC\User\Session $userSession */ $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) ->setMethods(['login']) ->getMock(); - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('getToken') ->with('doe') ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException())); @@ -341,11 +339,11 @@ class SessionTest extends \Test\TestCase { /** @var \OC\User\Session $userSession */ $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) ->setMethods(['login', 'isTwoFactorEnforced']) ->getMock(); - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('getToken') ->with('doe') ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException())); @@ -413,7 +411,7 @@ class SessionTest extends \Test\TestCase { //override, otherwise tests will fail because of setcookie() array('setMagicInCookie'), //there are passed as parameters to the constructor - array($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config)); + array($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config)); $granted = $userSession->loginWithCookie('foo', $token); @@ -458,7 +456,7 @@ class SessionTest extends \Test\TestCase { $token = 'goodToken'; \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $granted = $userSession->loginWithCookie('foo', 'badToken'); $this->assertSame($granted, false); @@ -501,7 +499,7 @@ class SessionTest extends \Test\TestCase { $token = 'goodToken'; \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $granted = $userSession->loginWithCookie('foo', $token); $this->assertSame($granted, false); @@ -526,7 +524,7 @@ class SessionTest extends \Test\TestCase { $session = new Memory(''); $session->set('user_id', 'foo'); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) ->setMethods([ 'validateSession' ]) @@ -542,6 +540,119 @@ class SessionTest extends \Test\TestCase { $this->assertEquals($users['bar'], $userSession->getUser()); } + public function testCreateSessionToken() { + $manager = $this->getMockBuilder('\OC\User\Manager') + ->disableOriginalConstructor() + ->getMock(); + $session = $this->getMock('\OCP\ISession'); + $token = $this->getMock('\OC\Authentication\Token\IToken'); + $user = $this->getMock('\OCP\IUser'); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + + $random = $this->getMock('\OCP\Security\ISecureRandom'); + $config = $this->getMock('\OCP\IConfig'); + $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'); + + $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password)); + } + + public function testCreateSessionTokenWithTokenPassword() { + $manager = $this->getMockBuilder('\OC\User\Manager') + ->disableOriginalConstructor() + ->getMock(); + $session = $this->getMock('\OCP\ISession'); + $token = $this->getMock('\OC\Authentication\Token\IToken'); + $user = $this->getMock('\OCP\IUser'); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + + $random = $this->getMock('\OCP\Security\ISecureRandom'); + $config = $this->getMock('\OCP\IConfig'); + $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 = 'iamatoken'; + $realPassword = '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->returnValue($token)); + $this->tokenProvider->expects($this->once()) + ->method('getPassword') + ->with($token, $password) + ->will($this->returnValue($realPassword)); + + $this->tokenProvider->expects($this->once()) + ->method('generateToken') + ->with($sessionId, $uid, $loginName, $realPassword, 'Firefox'); + + $this->assertTrue($userSession->createSessionToken($request, $uid, $loginName, $password)); + } + + public function testCreateSessionTokenWithNonExistentUser() { + $manager = $this->getMockBuilder('\OC\User\Manager') + ->disableOriginalConstructor() + ->getMock(); + $session = $this->getMock('\OCP\ISession'); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $request = $this->getMock('\OCP\IRequest'); + + $uid = 'user123'; + $loginName = 'User123'; + $password = 'passme'; + + $manager->expects($this->once()) + ->method('get') + ->with($uid) + ->will($this->returnValue(null)); + + $this->assertFalse($userSession->createSessionToken($request, $uid, $loginName, $password)); + } + public function testTryTokenLoginWithDisabledUser() { $manager = $this->getMockBuilder('\OC\User\Manager') ->disableOriginalConstructor() @@ -549,14 +660,14 @@ class SessionTest extends \Test\TestCase { $session = new Memory(''); $token = $this->getMock('\OC\Authentication\Token\IToken'); $user = $this->getMock('\OCP\IUser'); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); $request = $this->getMock('\OCP\IRequest'); $request->expects($this->once()) ->method('getHeader') ->with('Authorization') ->will($this->returnValue('token xxxxx')); - $this->defaultProvider->expects($this->once()) + $this->tokenProvider->expects($this->once()) ->method('validateToken') ->with('xxxxx') ->will($this->returnValue($token)); |