diff --git a/Security.MD b/Security.MD index 9eab4bf3a..35b89b446 100644 --- a/Security.MD +++ b/Security.MD @@ -8,7 +8,7 @@ In order to give the community time to respond and upgrade we strongly urge you ### Password Storage -OpenCATS uses MD5 hashing to store passwords. This will be replaced in future versions +OpenCATS hashes user passwords using PHP’s password_hash() and verifies them with password_verify(), using PASSWORD_DEFAULT (the default algorithm selected by the running PHP version). ### XSS diff --git a/db/cats_schema.sql b/db/cats_schema.sql index 37c551a95..033b654c7 100755 --- a/db/cats_schema.sql +++ b/db/cats_schema.sql @@ -859,7 +859,7 @@ insert into `module_schema`(`module_schema_id`,`name`,`version`) values (9,'ext insert into `module_schema`(`module_schema_id`,`name`,`version`) values (10,'graphs',0); insert into `module_schema`(`module_schema_id`,`name`,`version`) values (11,'home',0); insert into `module_schema`(`module_schema_id`,`name`,`version`) values (12,'import',0); -insert into `module_schema`(`module_schema_id`,`name`,`version`) values (13,'install',363); +insert into `module_schema`(`module_schema_id`,`name`,`version`) values (13,'install',365); insert into `module_schema`(`module_schema_id`,`name`,`version`) values (14,'joborders',0); insert into `module_schema`(`module_schema_id`,`name`,`version`) values (15,'lists',0); insert into `module_schema`(`module_schema_id`,`name`,`version`) values (16,'login',0); @@ -1072,7 +1072,7 @@ CREATE TABLE `user` ( `site_id` int(11) NOT NULL DEFAULT '0', `user_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `email` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, - `password` varchar(128) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', + `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `access_level` int(11) NOT NULL DEFAULT '100', `can_change_password` int(1) NOT NULL DEFAULT '1', `is_test_user` int(1) NOT NULL DEFAULT '0', @@ -1105,7 +1105,7 @@ CREATE TABLE `user` ( /*Data for the table `user` */ -insert into `user`(`user_id`,`site_id`,`user_name`,`email`,`password`,`access_level`,`can_change_password`,`is_test_user`,`last_name`,`first_name`,`is_demo`,`categories`,`session_cookie`,`pipeline_entries_per_page`,`column_preferences`,`force_logout`,`title`,`phone_work`,`phone_cell`,`phone_other`,`address`,`notes`,`company`,`city`,`state`,`zip_code`,`country`,`can_see_eeo_info`) values (1,1,'admin','admin@testdomain.com','admin',500,1,0,'Administrator','CATS',0,NULL,'CATS=e29233aabf2cdb71373582023ff9747e',15,'a:4:{s:31:\"home:ImportantPipelineDashboard\";a:6:{i:0;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:1;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:8:\"Position\";s:5:\"width\";i:275;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:210;}i:5;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:80;}}s:18:\"home:CallsDataGrid\";a:2:{i:0;a:2:{s:4:\"name\";s:4:\"Time\";s:5:\"width\";i:90;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:175;}}s:39:\"candidates:candidatesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:215;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:25:\"activity:ActivityDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:4:\"Date\";s:5:\"width\";i:110;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"Regarding\";s:5:\"width\";i:125;}i:4;a:2:{s:4:\"name\";s:8:\"Activity\";s:5:\"width\";i:65;}i:5;a:2:{s:4:\"name\";s:5:\"Notes\";s:5:\"width\";i:240;}i:6;a:2:{s:4:\"name\";s:10:\"Entered By\";s:5:\"width\";i:60;}}}',0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +insert into `user`(`user_id`,`site_id`,`user_name`,`email`,`password`,`access_level`,`can_change_password`,`is_test_user`,`last_name`,`first_name`,`is_demo`,`categories`,`session_cookie`,`pipeline_entries_per_page`,`column_preferences`,`force_logout`,`title`,`phone_work`,`phone_cell`,`phone_other`,`address`,`notes`,`company`,`city`,`state`,`zip_code`,`country`,`can_see_eeo_info`) values (1,1,'admin','admin@testdomain.com',md5('cats'),500,1,0,'Administrator','CATS',0,NULL,'CATS=e29233aabf2cdb71373582023ff9747e',15,'a:4:{s:31:\"home:ImportantPipelineDashboard\";a:6:{i:0;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:1;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:8:\"Position\";s:5:\"width\";i:275;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:210;}i:5;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:80;}}s:18:\"home:CallsDataGrid\";a:2:{i:0;a:2:{s:4:\"name\";s:4:\"Time\";s:5:\"width\";i:90;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:175;}}s:39:\"candidates:candidatesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:215;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:25:\"activity:ActivityDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:4:\"Date\";s:5:\"width\";i:110;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"Regarding\";s:5:\"width\";i:125;}i:4;a:2:{s:4:\"name\";s:8:\"Activity\";s:5:\"width\";i:65;}i:5;a:2:{s:4:\"name\";s:5:\"Notes\";s:5:\"width\";i:240;}i:6;a:2:{s:4:\"name\";s:10:\"Entered By\";s:5:\"width\";i:60;}}}',0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); insert into `user`(`user_id`,`site_id`,`user_name`,`email`,`password`,`access_level`,`can_change_password`,`is_test_user`,`last_name`,`first_name`,`is_demo`,`categories`,`session_cookie`,`pipeline_entries_per_page`,`column_preferences`,`force_logout`,`title`,`phone_work`,`phone_cell`,`phone_other`,`address`,`notes`,`company`,`city`,`state`,`zip_code`,`country`,`can_see_eeo_info`) values (1250,180,'cats@rootadmin','0','cantlogin',0,0,0,'Automated','CATS',0,NULL,NULL,15,NULL,0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); /*Table structure for table `user_login` */ diff --git a/installwizard.php b/installwizard.php index 911d5fd39..ba56d4ab6 100755 --- a/installwizard.php +++ b/installwizard.php @@ -416,7 +416,7 @@
You may now login to OpenCATS. If it is a new installation, use the following logon information:

Username: admin
- Password: admin
+ Password: cats


OpenCATS will periodically check for new versions of the software from catsone.com, and will send non confidential information about your diff --git a/lib/Users.php b/lib/Users.php old mode 100755 new mode 100644 index e4b75e615..5420b02c3 --- a/lib/Users.php +++ b/lib/Users.php @@ -90,7 +90,7 @@ public function add($lastName, $firstName, $email, $username, $password, $accessLevel, $eeoIsVisible = false, $userSiteID = -1) { - $md5pwd = $password == LDAPUSER_PASSWORD ? $password : md5($password); + $hashedPassword = $password == LDAPUSER_PASSWORD ? $password : $this->hashPassword($password); $userSiteID = $userSiteID < 0 ? $this->_siteID : $userSiteID; $sql = sprintf( "INSERT INTO user ( @@ -118,7 +118,7 @@ public function add($lastName, $firstName, $email, $username, $password, %s )", $this->_db->makeQueryString($username), - $this->_db->makeQueryString($md5pwd), + $this->_db->makeQueryString($hashedPassword), $this->_db->makeQueryInteger($accessLevel), $this->_db->makeQueryString($email), $this->_db->makeQueryString($firstName), @@ -676,7 +676,19 @@ public function changePassword($userID, $currentPassword, $newPassword) } /* Is the user's supplied password correct? */ - if ($rs['password'] !== md5($currentPassword)) + /* FIXME: This code relies on verifyAndMigratePassword() to handle both legacy + * MD5 hashes and modern password_hash() output. If verifyAndMigratePassword() + * is changed in a future release (for example when removing MD5 support or + * switching to a different algorithm), this password check must be reviewed + * and adjusted accordingly. + * + * Previous MD5-only implementation for reference: + * if ($rs['password'] !== md5($currentPassword)) + * { + * return LOGIN_INVALID_PASSWORD; + * } + */ + if (!$this->verifyAndMigratePassword($userID, $currentPassword, $rs['password'])) { return LOGIN_INVALID_PASSWORD; } @@ -694,14 +706,15 @@ public function changePassword($userID, $currentPassword, $newPassword) } /* Change the user's password. */ + $newPasswordHash = $this->hashPassword($newPassword); $sql = sprintf( "UPDATE user SET - password = md5(%s) + password = %s WHERE user.user_id = %s", - $this->_db->makeQueryString($newPassword), + $this->_db->makeQueryString($newPasswordHash), $this->_db->makeQueryInteger($userID) ); $this->_db->query($sql); @@ -748,14 +761,15 @@ public function resetPassword($userID, $newPassword) } /* Change the user's password. */ + $newPasswordHash = $this->hashPassword($newPassword); $sql = sprintf( "UPDATE user SET - password = md5(%s) + password = %s WHERE user.user_id = %s", - $this->_db->makeQueryString($newPassword), + $this->_db->makeQueryString($newPasswordHash), $this->_db->makeQueryInteger($userID) ); $this->_db->query($sql); @@ -798,7 +812,8 @@ public function isCorrectLogin($username, $password) "SELECT user.user_name AS username, user.password AS password, - user.access_level AS accessLevel + user.access_level AS accessLevel, + user.user_id AS userID FROM user WHERE @@ -837,10 +852,12 @@ public function isCorrectLogin($username, $password) return LOGIN_INVALID_USER; } else { /* Is the user's supplied password correct? */ - if ($rs['password'] !== md5($password)) + if (!$this->verifyAndMigratePassword((int) $rs['userID'], $password, $rs['password'])) { return LOGIN_INVALID_PASSWORD; } + + $this->rehashPasswordIfNeeded((int) $rs['userID'], $rs['password'], $password); } if (!$existsInDB && $existsInLDAP) { @@ -1236,6 +1253,81 @@ public function getAutomatedUser() return $rs; } + private function hashPassword($password) + { + return password_hash($password, PASSWORD_DEFAULT); + } + + /** + * Upgrades an existing password hash to the current PASSWORD_DEFAULT algorithm/options + * after a successful login, if password_needs_rehash() indicates that an update + * is required. + * + * @param int $userID ID of the user whose password hash may be updated. + * @param string $storedHash Hash value as it was read from the database before verification. + * @param string $password Plain-text password that was just successfully verified. + * + * @return void + */ + private function rehashPasswordIfNeeded($userID, $storedHash, $password) + { + if ($this->isLegacyPasswordHash($storedHash) || $storedHash === LDAPUSER_PASSWORD) + { + return; + } + + if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) + { + $this->updatePasswordHash($userID, $password); + } + } + + /* FIXME: The following methods exist only for backwards compatibility with legacy MD5 password hashes. + * They also perform a one-time lazy migration from MD5 to password_hash(). + * After several releases with the new algorithm in place, this MD5-related code should be removed + * from the codebase. + */ + + private function isLegacyPasswordHash($hash) + { + return (bool) preg_match('/^[0-9a-f]{32}$/i', $hash); + } + + private function verifyAndMigratePassword($userID, $password, $storedHash) + { + if ($this->isLegacyPasswordHash($storedHash)) + { + if (md5($password) !== $storedHash) + { + return false; + } + + $this->updatePasswordHash($userID, $password); + + return true; + } + + return password_verify($password, $storedHash); + } + + private function updatePasswordHash($userID, $password) + { + $sql = sprintf( + "UPDATE + user + SET + password = %s + WHERE + user.user_id = %s", + $this->_db->makeQueryString($this->hashPassword($password)), + $this->_db->makeQueryInteger($userID) + ); + + $this->_db->query($sql); + } + + // End of temporary MD5 compatibility and lazy migration code. + public function isUserLDAP($userID) { $sql = sprintf( diff --git a/modules/install/Schema.php b/modules/install/Schema.php index 495405504..6a98eb076 100755 --- a/modules/install/Schema.php +++ b/modules/install/Schema.php @@ -1328,6 +1328,10 @@ public static function get() '364' => ' UPDATE user SET password = md5(password) WHERE can_change_password=1; ', + '365' => ' + ALTER TABLE `user` + MODIFY `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT \'\'; + ', ); } diff --git a/modules/install/ajax/ui.php b/modules/install/ajax/ui.php index 53db04e79..b512f5af5 100755 --- a/modules/install/ajax/ui.php +++ b/modules/install/ajax/ui.php @@ -1045,7 +1045,7 @@ MySQLConnect(); /* Determine if a default user is set. */ - $rs = MySQLQuery("SELECT * FROM user WHERE user_name = 'admin' AND password = 'cats'"); + $rs = MySQLQuery("SELECT * FROM user WHERE user_name = 'admin' AND password = md5('cats')"); if ($rs && mysqli_fetch_row($rs)) { //Default user set diff --git a/test/data/test.sql b/test/data/test.sql index 18748e05b..5037dde81 100644 --- a/test/data/test.sql +++ b/test/data/test.sql @@ -1615,7 +1615,7 @@ CREATE TABLE `user` ( LOCK TABLES `user` WRITE; /*!40000 ALTER TABLE `user` DISABLE KEYS */; -INSERT INTO `user` VALUES (1,1,'admin','admin@testdomain.com','21232f297a57a5a743894a0e4a801fc3',500,1,0,'Administrator','CATS',0,NULL,'CATS=63141ada1735df1a81579c547b172ca0',15,'a:11:{s:31:\"home:ImportantPipelineDashboard\";a:6:{i:0;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:1;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:8:\"Position\";s:5:\"width\";i:275;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:210;}i:5;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:80;}}s:18:\"home:CallsDataGrid\";a:2:{i:0;a:2:{s:4:\"name\";s:4:\"Time\";s:5:\"width\";i:90;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:175;}}s:39:\"candidates:candidatesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";s:3:\"119\";}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";s:3:\"149\";}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";s:3:\"280\";}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";s:2:\"72\";}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:25:\"activity:ActivityDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:4:\"Date\";s:5:\"width\";i:110;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"Regarding\";s:5:\"width\";i:125;}i:4;a:2:{s:4:\"name\";s:8:\"Activity\";s:5:\"width\";i:65;}i:5;a:2:{s:4:\"name\";s:5:\"Notes\";s:5:\"width\";i:240;}i:6;a:2:{s:4:\"name\";s:10:\"Entered By\";s:5:\"width\";i:60;}}s:37:\"joborders:JobOrdersListByViewDataGrid\";a:12:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:2:\"ID\";s:5:\"width\";i:26;}i:2;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:55;}i:3;a:2:{s:4:\"name\";s:5:\"Title\";s:5:\"width\";i:170;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:135;}i:5;a:2:{s:4:\"name\";s:4:\"Type\";s:5:\"width\";i:30;}i:6;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:40;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:55;}i:8;a:2:{s:4:\"name\";s:3:\"Age\";s:5:\"width\";i:30;}i:9;a:2:{s:4:\"name\";s:9:\"Submitted\";s:5:\"width\";i:18;}i:10;a:2:{s:4:\"name\";s:8:\"Pipeline\";s:5:\"width\";i:18;}i:11;a:2:{s:4:\"name\";s:9:\"Recruiter\";s:5:\"width\";i:65;}}s:37:\"companies:CompaniesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:255;}i:2;a:2:{s:4:\"name\";s:4:\"Jobs\";s:5:\"width\";i:40;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:90;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:5:\"Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:35:\"contacts:ContactsListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:80;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:80;}i:3;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:135;}i:4;a:2:{s:4:\"name\";s:5:\"Title\";s:5:\"width\";i:135;}i:5;a:2:{s:4:\"name\";s:10:\"Work Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:85;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:19:\"lists:ListsDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:5:\"Count\";s:5:\"width\";i:45;}i:1;a:2:{s:4:\"name\";s:11:\"Description\";s:5:\"width\";i:355;}i:2;a:2:{s:4:\"name\";s:9:\"Data Type\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"List Type\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:75;}i:5;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:6;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:53:\"candidates:candidatesSavedListByViewDataGrid:s:1:\"1\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:200;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:13:\"Added To List\";s:5:\"width\";i:75;}}s:53:\"candidates:candidatesSavedListByViewDataGrid:s:1:\"2\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:200;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:13:\"Added To List\";s:5:\"width\";i:75;}}s:51:\"companies:companiesSavedListByViewDataGrid:s:1:\"3\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:255;}i:2;a:2:{s:4:\"name\";s:4:\"Jobs\";s:5:\"width\";i:40;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:90;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:5:\"Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}}',0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0),(1250,180,'cats@rootadmin','0','cantlogin',0,0,0,'Automated','CATS',0,NULL,NULL,15,NULL,0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO `user` VALUES (1,1,'admin','admin@testdomain.com','0832c1202da8d382318e329a7c133ea0',500,1,0,'Administrator','CATS',0,NULL,'CATS=63141ada1735df1a81579c547b172ca0',15,'a:11:{s:31:\"home:ImportantPipelineDashboard\";a:6:{i:0;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:1;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:8:\"Position\";s:5:\"width\";i:275;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:210;}i:5;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:80;}}s:18:\"home:CallsDataGrid\";a:2:{i:0;a:2:{s:4:\"name\";s:4:\"Time\";s:5:\"width\";i:90;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:175;}}s:39:\"candidates:candidatesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";s:3:\"119\";}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";s:3:\"149\";}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";s:3:\"280\";}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";s:2:\"72\";}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:25:\"activity:ActivityDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:4:\"Date\";s:5:\"width\";i:110;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:85;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"Regarding\";s:5:\"width\";i:125;}i:4;a:2:{s:4:\"name\";s:8:\"Activity\";s:5:\"width\";i:65;}i:5;a:2:{s:4:\"name\";s:5:\"Notes\";s:5:\"width\";i:240;}i:6;a:2:{s:4:\"name\";s:10:\"Entered By\";s:5:\"width\";i:60;}}s:37:\"joborders:JobOrdersListByViewDataGrid\";a:12:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:2:\"ID\";s:5:\"width\";i:26;}i:2;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:55;}i:3;a:2:{s:4:\"name\";s:5:\"Title\";s:5:\"width\";i:170;}i:4;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:135;}i:5;a:2:{s:4:\"name\";s:4:\"Type\";s:5:\"width\";i:30;}i:6;a:2:{s:4:\"name\";s:6:\"Status\";s:5:\"width\";i:40;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:55;}i:8;a:2:{s:4:\"name\";s:3:\"Age\";s:5:\"width\";i:30;}i:9;a:2:{s:4:\"name\";s:9:\"Submitted\";s:5:\"width\";i:18;}i:10;a:2:{s:4:\"name\";s:8:\"Pipeline\";s:5:\"width\";i:18;}i:11;a:2:{s:4:\"name\";s:9:\"Recruiter\";s:5:\"width\";i:65;}}s:37:\"companies:CompaniesListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:255;}i:2;a:2:{s:4:\"name\";s:4:\"Jobs\";s:5:\"width\";i:40;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:90;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:5:\"Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:35:\"contacts:ContactsListByViewDataGrid\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:80;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:80;}i:3;a:2:{s:4:\"name\";s:7:\"Company\";s:5:\"width\";i:135;}i:4;a:2:{s:4:\"name\";s:5:\"Title\";s:5:\"width\";i:135;}i:5;a:2:{s:4:\"name\";s:10:\"Work Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:85;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:19:\"lists:ListsDataGrid\";a:7:{i:0;a:2:{s:4:\"name\";s:5:\"Count\";s:5:\"width\";i:45;}i:1;a:2:{s:4:\"name\";s:11:\"Description\";s:5:\"width\";i:355;}i:2;a:2:{s:4:\"name\";s:9:\"Data Type\";s:5:\"width\";i:75;}i:3;a:2:{s:4:\"name\";s:9:\"List Type\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:75;}i:5;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:6;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}s:53:\"candidates:candidatesSavedListByViewDataGrid:s:1:\"1\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:200;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:13:\"Added To List\";s:5:\"width\";i:75;}}s:53:\"candidates:candidatesSavedListByViewDataGrid:s:1:\"2\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:31;}i:1;a:2:{s:4:\"name\";s:10:\"First Name\";s:5:\"width\";i:75;}i:2;a:2:{s:4:\"name\";s:9:\"Last Name\";s:5:\"width\";i:85;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:75;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:10:\"Key Skills\";s:5:\"width\";i:200;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:13:\"Added To List\";s:5:\"width\";i:75;}}s:51:\"companies:companiesSavedListByViewDataGrid:s:1:\"3\";\";a:9:{i:0;a:2:{s:4:\"name\";s:11:\"Attachments\";s:5:\"width\";i:10;}i:1;a:2:{s:4:\"name\";s:4:\"Name\";s:5:\"width\";i:255;}i:2;a:2:{s:4:\"name\";s:4:\"Jobs\";s:5:\"width\";i:40;}i:3;a:2:{s:4:\"name\";s:4:\"City\";s:5:\"width\";i:90;}i:4;a:2:{s:4:\"name\";s:5:\"State\";s:5:\"width\";i:50;}i:5;a:2:{s:4:\"name\";s:5:\"Phone\";s:5:\"width\";i:85;}i:6;a:2:{s:4:\"name\";s:5:\"Owner\";s:5:\"width\";i:65;}i:7;a:2:{s:4:\"name\";s:7:\"Created\";s:5:\"width\";i:60;}i:8;a:2:{s:4:\"name\";s:8:\"Modified\";s:5:\"width\";i:60;}}}',0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0),(1250,180,'cats@rootadmin','0','cantlogin',0,0,0,'Automated','CATS',0,NULL,NULL,15,NULL,0,'','','','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); /*!40000 ALTER TABLE `user` ENABLE KEYS */; UNLOCK TABLES; diff --git a/test/features/bootstrap/FeatureContext.php b/test/features/bootstrap/FeatureContext.php index d3eb75e7b..e327c2451 100644 --- a/test/features/bootstrap/FeatureContext.php +++ b/test/features/bootstrap/FeatureContext.php @@ -37,7 +37,7 @@ class FeatureContext extends MinkContext implements Context, SnippetAcceptingCon public function __construct() { $this->roleData = array( - 'Administrator' => new Role('admin', 'admin'), + 'Administrator' => new Role('admin', 'cats'), 'User' => new Role('john@mycompany.net', 'john99') ); } diff --git a/test/features/login.feature b/test/features/login.feature index ac60cbf0d..53dbbca01 100644 --- a/test/features/login.feature +++ b/test/features/login.feature @@ -34,7 +34,7 @@ Feature: Login Scenario: Login as administrator Given I am on "/" And I fill in "Username" with "admin" - And I fill in "Password" with "admin" + And I fill in "Password" with "cats" When I press "Login" Then I should not see "Invalid username or password" And I should see "Administrator" @@ -62,4 +62,4 @@ Feature: Login And I should not see "Add Job Orders" - \ No newline at end of file +