Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EZP-19123: Make ezuser.login case in-sensitive across databases #1561

Merged
merged 6 commits into from Feb 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion bin/.travis/prepare_unittest.sh
Expand Up @@ -3,7 +3,11 @@
# File for setting up system for unit/integration testing

# Disable xdebug to speed things up as we don't currently generate coverge on travis
if [ "$TRAVIS_PHP_VERSION" != "hhvm" ] ; then phpenv config-rm xdebug.ini ; fi
# And make sure we use UTF-8 encoding
if [ "$TRAVIS_PHP_VERSION" != "hhvm" ] ; then
phpenv config-rm xdebug.ini
echo "default_charset = UTF-8" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
fi

# Setup DB
if [ "$DB" = "mysql" ] ; then mysql -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;" -uroot ; fi
Expand Down
4 changes: 2 additions & 2 deletions data/cleandata.sql
Expand Up @@ -1967,8 +1967,8 @@ INSERT INTO `ezurlalias_ml_incr` (`id`) VALUES (35);
INSERT INTO `ezurlalias_ml_incr` (`id`) VALUES (36);
INSERT INTO `ezurlalias_ml_incr` (`id`) VALUES (37);

INSERT INTO `ezuser` (`contentobject_id`, `email`, `login`, `password_hash`, `password_hash_type`) VALUES (10,'nospam@ez.no','anonymous','4e6f6184135228ccd45f8233d72a0363',2);
INSERT INTO `ezuser` (`contentobject_id`, `email`, `login`, `password_hash`, `password_hash_type`) VALUES (14,'nospam@ez.no','admin','c78e3b0f3d9244ed8c6d1c29464bdff9',2);
INSERT INTO `ezuser` (`contentobject_id`, `email`, `login`, `login_normalized`, `password_hash`, `password_hash_type`) VALUES (10,'nospam@ez.no','anonymous','anonymous','4e6f6184135228ccd45f8233d72a0363',2);
INSERT INTO `ezuser` (`contentobject_id`, `email`, `login`, `login_normalized`, `password_hash`, `password_hash_type`) VALUES (14,'nospam@ez.no','admin','admin','c78e3b0f3d9244ed8c6d1c29464bdff9',2);

INSERT INTO `ezuser_role` (`contentobject_id`, `id`, `limit_identifier`, `limit_value`, `role_id`) VALUES (11,28,'','',1);
INSERT INTO `ezuser_role` (`contentobject_id`, `id`, `limit_identifier`, `limit_value`, `role_id`) VALUES (42,31,'','',1);
Expand Down
3 changes: 2 additions & 1 deletion data/mysql/schema.sql
Expand Up @@ -2239,10 +2239,11 @@ CREATE TABLE `ezuser` (
`contentobject_id` int(11) NOT NULL DEFAULT '0',
`email` varchar(150) NOT NULL DEFAULT '',
`login` varchar(150) NOT NULL DEFAULT '',
`login_normalized` varchar(150) NOT NULL DEFAULT '',
`password_hash` varchar(50) DEFAULT NULL,
`password_hash_type` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`contentobject_id`),
KEY `ezuser_login` (`login`)
UNIQUE KEY `ezuser_login` (`login_normalized`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

Expand Down
10 changes: 10 additions & 0 deletions data/update/mysql/unstable/dbupdate-6.1.0-to-6.2.0rc1.sql
@@ -0,0 +1,10 @@
SET default_storage_engine=InnoDB;
-- Set storage engine schema version number
UPDATE ezsite_data SET value='6.2.0' WHERE name='ezpublish-version';

--
-- EZP-19123: Make ezuser.login case in-sensitive across databases
--

ALTER TABLE ezuser ADD COLUMN login_normalized varchar(150) NOT NULL DEFAULT '';
ALTER TABLE ezuser DROP KEY ezuser_login, ADD UNIQUE KEY ezuser_login (login_normalized);
9 changes: 9 additions & 0 deletions data/update/postgres/unstable/dbupdate-6.1.0-to-6.2.0rc1.sql
@@ -0,0 +1,9 @@
-- Set storage engine schema version number
UPDATE ezsite_data SET value='6.2.0' WHERE name='ezpublish-version';

--
-- EZP-19123: Make ezuser.login case in-sensitive across databases
--

ALTER TABLE ezuser ADD login_normalized character varying(150) DEFAULT ''::character varying NOT NULL;
ALTER TABLE ezuser DROP CONSTRAINT ezuser_login, ADD CONSTRAINT ezuser_login UNIQUE KEY (login_normalized);
38 changes: 37 additions & 1 deletion eZ/Publish/API/Repository/Tests/UserServiceTest.php
Expand Up @@ -1160,7 +1160,7 @@ public function testLoadUserByCredentialsThrowsNotFoundExceptionForUnknownLogin(

// This call will fail with a "NotFoundException", because the given
// login/password combination does not exist.
$userService->loadUserByCredentials('USER', 'secret');
$userService->loadUserByCredentials('üser', 'secret');
/* END: Use Case */
}

Expand Down Expand Up @@ -1244,6 +1244,42 @@ public function testLoadUserByLoginThrowsNotFoundExceptionForUnknownLogin()
/* END: Use Case */
}

/**
* Test for the loadUserByLogin() method.
*
* @see \eZ\Publish\API\Repository\UserService::loadUserByLogin()
* @depends eZ\Publish\API\Repository\Tests\UserServiceTest::testLoadUserByLogin
*/
public function testLoadUserByLoginWorksForLoginWithWrongCase()
{
$repository = $this->getRepository();

$userService = $repository->getUserService();

/* BEGIN: Use Case */
$user = $this->createUserVersion1();

// Lookup by user login should ignore casing
$userReloaded = $userService->loadUserByLogin('USER');
/* END: Use Case */

$this->assertPropertiesCorrect(
array(
'login' => $user->login,
'email' => $user->email,
'passwordHash' => $user->passwordHash,
'hashAlgorithm' => $user->hashAlgorithm,
'enabled' => $user->enabled,
'maxLogin' => $user->maxLogin,
'id' => $user->id,
'contentInfo' => $user->contentInfo,
'versionInfo' => $user->versionInfo,
'fields' => $user->fields,
),
$userReloaded
);
}

/**
* Test for the loadUsersByEmail() method.
*
Expand Down
9 changes: 5 additions & 4 deletions eZ/Publish/API/Repository/UserService.php
Expand Up @@ -148,8 +148,8 @@ public function loadAnonymousUser();
/**
* Loads a user for the given login and password.
*
* This method is case sensitive in regards to $login and $password as a comparison of password hash is done
* which contains both parameters.
* Since 6.1 login is case-insensitive across all storage engines and database backends, however if login
* is part of the password hash this method will essentially be case sensitive.
*
* @param string $login
* @param string $password the plain password
Expand All @@ -164,7 +164,8 @@ public function loadUserByCredentials($login, $password);
/**
* Loads a user for the given login.
*
* Note: This method loads user by $login where $login might be case in-sensitive on certain storage engines!
* Since 6.1 login is case-insensitive across all storage engines and database backends, like was the case
* with mysql before in eZ Publish 3.x/4.x/5.x.
*
* @param string $login
*
Expand All @@ -177,7 +178,7 @@ public function loadUserByLogin($login);
/**
* Loads a user for the given email.
*
* Note: This method loads user by $email where $email might be case in-sensitive on certain storage engines!
* Note: This method loads user by $email where $email might be case-insensitive on certain storage engines!
*
* Returns an array of Users since eZ Publish has under certain circumstances allowed
* several users having same email in the past (by means of a configuration option).
Expand Down
Expand Up @@ -195,11 +195,11 @@ public function testUpdateUser()

$handler->create($user = $this->getValidUser());

$user->login = 'new_login';
$user->login = 'New_lögin';
$handler->update($user);

$this->assertQueryResult(
array(array(42, 'kore@example.org', 'new_login', 1234567890, '2')),
array(array(42, 'kore@example.org', 'New_lögin', 'new_lögin', 1234567890, '2')),
$this->handler->createSelectQuery()->select('*')->from('ezuser'),
'Expected user data to be updated.'
);
Expand Down
Expand Up @@ -482,9 +482,11 @@ CREATE TABLE ezuser (
contentobject_id int(11) NOT NULL DEFAULT 0,
email varchar(150) NOT NULL DEFAULT '',
login varchar(150) NOT NULL DEFAULT '',
login_normalized varchar(150) NOT NULL DEFAULT '',
password_hash varchar(50) DEFAULT NULL,
password_hash_type int(11) NOT NULL DEFAULT 1,
PRIMARY KEY (contentobject_id)
PRIMARY KEY (contentobject_id),
UNIQUE KEY `ezuser_login` (`login_normalized`)
) ENGINE=InnoDB;

DROP TABLE IF EXISTS ezuser_role;
Expand Down
Expand Up @@ -512,6 +512,7 @@ CREATE TABLE ezuser (
contentobject_id integer DEFAULT 0 NOT NULL,
email character varying(150) DEFAULT ''::character varying NOT NULL,
login character varying(150) DEFAULT ''::character varying NOT NULL,
login_normalized character varying(150) DEFAULT ''::character varying NOT NULL,
password_hash character varying(50),
password_hash_type integer DEFAULT 1 NOT NULL
);
Expand Down Expand Up @@ -729,7 +730,7 @@ CREATE INDEX ezurlalias_ml_text ON ezurlalias_ml USING btree (text, id, link);

CREATE INDEX ezurlalias_ml_text_lang ON ezurlalias_ml USING btree (text, lang_mask, parent);

CREATE INDEX ezuser_login ON ezuser USING btree (login);
CREATE UNIQUE INDEX ezuser_login ON ezuser USING btree (login_normalized);

CREATE INDEX hash_key ON ezuser_accountkey USING btree (hash_key);

Expand Down
Expand Up @@ -432,10 +432,12 @@ CREATE TABLE ezuser (
contentobject_id integer NOT NULL DEFAULT 0,
email text(150) NOT NULL,
login text(150) NOT NULL,
login_normalized text(150) NOT NULL,
password_hash text(50),
password_hash_type integer NOT NULL DEFAULT 1,
PRIMARY KEY (contentobject_id)
);
CREATE UNIQUE INDEX ezuser_login ON ezuser (login_normalized);

CREATE TABLE ezuser_role (
contentobject_id integer,
Expand Down
Expand Up @@ -54,6 +54,9 @@ public function createUser(User $user)
)->set(
$this->handler->quoteColumn('login'),
$query->bindValue($user->login)
)->set(
$this->handler->quoteColumn('login_normalized'),
$query->bindValue(mb_strtolower($user->login, 'UTF-8'))
)->set(
$this->handler->quoteColumn('email'),
$query->bindValue($user->email)
Expand Down Expand Up @@ -179,8 +182,8 @@ public function loadByLogin($login)
)
)->where(
$query->expr->eq(
$this->handler->quoteColumn('login', 'ezuser'),
$query->bindValue($login, null, \PDO::PARAM_STR)
$this->handler->quoteColumn('login_normalized', 'ezuser'),
$query->bindValue(mb_strtolower($login, 'UTF-8'), null, \PDO::PARAM_STR)
)
);

Expand Down Expand Up @@ -242,6 +245,9 @@ public function updateUser(User $user)
->set(
$this->handler->quoteColumn('login'),
$query->bindValue($user->login)
)->set(
$this->handler->quoteColumn('login_normalized'),
$query->bindValue(mb_strtolower($user->login, 'UTF-8'))
)->set(
$this->handler->quoteColumn('email'),
$query->bindValue($user->email)
Expand Down
Expand Up @@ -11462,13 +11462,15 @@
'contentobject_id' => '10',
'email' => 'nospam@ez.no',
'login' => 'anonymous',
'login_normalized' => 'anonymous',
'password_hash' => '4e6f6184135228ccd45f8233d72a0363',
'password_hash_type' => '2',
),
1 => array(
'contentobject_id' => '14',
'email' => 'spam@ez.no',
'login' => 'admin',
'login_normalized' => 'admin',
'password_hash' => 'c78e3b0f3d9244ed8c6d1c29464bdff9',
'password_hash_type' => '2',
),
Expand Down
Expand Up @@ -13091,13 +13091,15 @@
'contentobject_id' => '10',
'email' => 'nospam@ez.no',
'login' => 'anonymous',
'login_normalized' => 'anonymous',
'password_hash' => '4e6f6184135228ccd45f8233d72a0363',
'password_hash_type' => '2',
),
1 => array(
'contentobject_id' => '14',
'email' => 'spam@ez.no',
'login' => 'admin',
'login_normalized' => 'admin',
'password_hash' => 'c78e3b0f3d9244ed8c6d1c29464bdff9',
'password_hash_type' => '2',
),
Expand Down
7 changes: 5 additions & 2 deletions eZ/Publish/Core/Repository/UserService.php
Expand Up @@ -554,6 +554,8 @@ public function loadAnonymousUser()
/**
* Loads a user for the given login and password.
*
* {@inheritdoc}
*
* @param string $login
* @param string $password the plain password
*
Expand Down Expand Up @@ -593,6 +595,8 @@ public function loadUserByCredentials($login, $password)
/**
* Loads a user for the given login.
*
* {@inheritdoc}
*
* @param string $login
*
* @return \eZ\Publish\API\Repository\Values\User\User
Expand All @@ -613,8 +617,7 @@ public function loadUserByLogin($login)
/**
* Loads a user for the given email.
*
* Returns an array of Users since eZ Publish has under certain circumstances allowed
* several users having same email in the past (by means of a configuration option).
* {@inheritdoc}
*
* @param string $email
*
Expand Down
3 changes: 3 additions & 0 deletions eZ/Publish/Core/Search/Legacy/Tests/_fixtures/full_dump.php
Expand Up @@ -47667,6 +47667,7 @@
'contentobject_id' => '10',
'email' => 'nospam@ez.no',
'login' => 'anonymous',
'login_normalized' => 'anonymous',
'password_hash' => '4e6f6184135228ccd45f8233d72a0363',
'password_hash_type' => '2',
),
Expand All @@ -47675,6 +47676,7 @@
'contentobject_id' => '14',
'email' => 'kn@ez.no',
'login' => 'admin',
'login_normalized' => 'admin',
'password_hash' => 'c78e3b0f3d9244ed8c6d1c29464bdff9',
'password_hash_type' => '2',
),
Expand All @@ -47683,6 +47685,7 @@
'contentobject_id' => '226',
'email' => 'pa@ez.no',
'login' => 'a_member',
'login_normalized' => 'a_member',
'password_hash' => 'c78e3b0f3d9244ed8c6d1c29464bdff9',
'password_hash_type' => '2',
),
Expand Down
7 changes: 5 additions & 2 deletions eZ/Publish/Core/SignalSlot/UserService.php
Expand Up @@ -258,6 +258,8 @@ public function loadAnonymousUser()
/**
* Loads a user for the given login and password.
*
* {@inheritdoc}
*
* @param string $login
* @param string $password the plain password
*
Expand All @@ -274,6 +276,8 @@ public function loadUserByCredentials($login, $password)
/**
* Loads a user for the given login.
*
* {@inheritdoc}
*
* @param string $login
*
* @return \eZ\Publish\API\Repository\Values\User\User
Expand All @@ -288,8 +292,7 @@ public function loadUserByLogin($login)
/**
* Loads a user for the given email.
*
* Returns an array of Users since eZ Publish has under certain circumstances allowed
* several users having same email in the past (by means of a configuration option).
* {@inheritdoc}
*
* @param string $email
*
Expand Down