From 25d00f2fcb30925e6e9c32e00bf304566a623419 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Fri, 22 Mar 2013 18:33:49 +0100 Subject: [PATCH] Various updates. --- composer.lock | 8 +-- lib/Application.php | 41 ++++++++--- lib/Bean/User.php | 27 +++++-- lib/DI.php | 51 +------------- lib/JSONDatabase.php | 163 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 68 deletions(-) create mode 100644 lib/JSONDatabase.php diff --git a/composer.lock b/composer.lock index 7d046a725..4dbe30891 100644 --- a/composer.lock +++ b/composer.lock @@ -188,12 +188,12 @@ "source": { "type": "git", "url": "https://github.com/vatesfr/rekodi.git", - "reference": "b95faecb9b5b0f9e541a0cf8aac680cad834a4be" + "reference": "a0122f7958e9375626d265497b1bfef62c552915" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vatesfr/rekodi/zipball/b95faecb9b5b0f9e541a0cf8aac680cad834a4be", - "reference": "b95faecb9b5b0f9e541a0cf8aac680cad834a4be", + "url": "https://api.github.com/repos/vatesfr/rekodi/zipball/a0122f7958e9375626d265497b1bfef62c552915", + "reference": "a0122f7958e9375626d265497b1bfef62c552915", "shasum": "" }, "require": { @@ -222,7 +222,7 @@ "keywords": [ "event" ], - "time": "2013-03-22 12:24:15" + "time": "2013-03-22 15:41:39" } ], "packages-dev": [ diff --git a/lib/Application.php b/lib/Application.php index 44481c746..1735efc33 100644 --- a/lib/Application.php +++ b/lib/Application.php @@ -271,7 +271,7 @@ final class Application extends Base // Creates the user. $user = $users->create(array( 'name' => $name, - 'password' => password_hash($password, PASSWORD_DEFAULT), + 'password' => $password, 'permission' => $permission, )); @@ -343,12 +343,11 @@ final class Application extends Base // Checks the new password is valid. if (($new === $old) - || !User::check('password', $new)) + || !$user->checkAndSet('password', $new)) { return array(2, 'invalid password'); } - $user->password = password_hash($new, PASSWORD_DEFAULT); $users->save($user); // Returns success. @@ -371,6 +370,10 @@ final class Application extends Base null, array('id', 'name', 'permission') ); + foreach ($users as &$user) + { + $user['permission'] = User::permissionToString($user['permission']); + } $c->respond($id, $users); } @@ -385,7 +388,7 @@ final class Application extends Base { return -32602; // Invalid params. } - list($id, $properties) = $params; + list($uid, $properties) = $params; if (!$c->isAuthenticated() || !$this->_checkPermission($c->uid, User::ADMIN)) @@ -394,15 +397,36 @@ final class Application extends Base } $users = $this->_di->get('users'); - $user = $users->get($id); + + // Checks user exists and is not the current user. + if (($uid === $c->uid) + || !($user = $users->get($uid, false))) + { + return array(1, 'invalid user'); + } foreach ($properties as $field => $value) { switch ($field) { case 'name': + if (!$user->checkAndSet('name', $value)) + { + return array(3, 'invalid user name'); + } + break; case 'password': + if (!$user->checkAndSet('password', $value)) + { + return array(4, 'invalid password'); + } + break; case 'permission': + if (!$user->checkAndSet('permission', $value)) + { + return array(5, 'invalid permission '.$value); + } + break; default: return array(2, 'invalid property'); } @@ -550,16 +574,15 @@ final class Application extends Base if (!$vm) { $manager->create($properties); + echo "new VM: $id\n"; } else { $vm->set($properties, true); - $keys = array_keys($vm->getDirty()); - sort($keys); - $dirty = implode(', ', $keys); $manager->save($vm); - echo "updated VM: $id ($dirty)\n"; + + echo "updated VM: $id\n"; } } } diff --git a/lib/Bean/User.php b/lib/Bean/User.php index c430f4bd9..f69a5191d 100644 --- a/lib/Bean/User.php +++ b/lib/Bean/User.php @@ -25,7 +25,7 @@ namespace Bean; /** - * + * @todo Migrate check() and checkAndSet() to \Rekodi\Bean. */ final class User extends \Rekodi\Bean { @@ -112,10 +112,13 @@ final class User extends \Rekodi\Bean && preg_match('/^[a-z0-9]+(?:[-_.][a-z0-9]+)*$/', $value) ); case 'password': - return ( - is_string($value) - && preg_match('/^.{8,}$/', $value) - ); + if (!is_string($value) + || !preg_match('/^.{8,}$/', $value)) + { + return false; + } + $value = password_hash($value, PASSWORD_DEFAULT); + return true; case 'permission': $value = self::permissionFromString($value); return (false !== $value); @@ -124,6 +127,20 @@ final class User extends \Rekodi\Bean return false; } + /** + * + */ + function checkAndSet($field, $value) + { + if (!self::check($field, $value)) + { + return false; + } + + $this->__set($field, $value); + return true; + } + protected static $_fields; } User::init(); diff --git a/lib/DI.php b/lib/DI.php index 64e12945d..716ceba6f 100644 --- a/lib/DI.php +++ b/lib/DI.php @@ -84,56 +84,7 @@ final class DI extends Base ); } - $file = $config['database.file']; - if (file_exists($file)) - { - $data = @file_get_contents($file); - if ((false === $data) - || (null === ($data = json_decode($data, true)))) - { - trigger_error( - 'could not read the database', - E_USER_ERROR - ); - } - - return \Rekodi\Manager\Memory::createFromState($data); - } - - $manager = new \Rekodi\Manager\Memory; - - // Create tables. - $manager->createTable('tokens', function ($table) { - $table - ->string('id')->unique() - ->integer('expiration') - ->string('user_id') - ; - }); - $manager->createTable('users', function ($table) { - $table - ->integer('id')->autoIncremented() - ->string('name')->unique() - ->string('password') - ->integer('permission') - ; - }); - - // Insert initial data. - $manager->create('users', array( - array( - 'name' => 'admin', - 'password' => '$2y$10$VzBQqiwnhG5zc2.MQmmW4ORcPW6FE7SLhPr1VBV2ubn5zJoesnmli', - 'permission' => \Bean\User::ADMIN, - ), - )); - - trigger_error( - 'no existing database, creating default user (admin:admin)', - E_USER_WARNING - ); - - return $manager; + return JSONDatabase::factory($config['database.file']); } private function _init_errorLogger() diff --git a/lib/JSONDatabase.php b/lib/JSONDatabase.php new file mode 100644 index 000000000..2ce967614 --- /dev/null +++ b/lib/JSONDatabase.php @@ -0,0 +1,163 @@ +. + * + * @author Julien Fontanet + * @license http://www.gnu.org/licenses/gpl-3.0-standalone.html GPLv3 + * + * @package Xen Orchestra Server + */ + +final class JSONDatabase extends \Rekodi\Manager\Memory +{ + /** + * + */ + static function factory($file) + { + if (file_exists($file)) + { + $data = @file_get_contents($file); + if ((false === $data) + || (null === ($data = json_decode($data, true)))) + { + trigger_error( + 'could not read the database', + E_USER_ERROR + ); + } + + $manager = static::createFromState($data); + } + else + { + $manager = new static; + + // Create tables. + $manager->createTable('tokens', function ($table) { + $table + ->string('id')->unique() + ->integer('expiration') + ->string('user_id') + ; + }); + $manager->createTable('users', function ($table) { + $table + ->integer('id')->autoIncremented() + ->string('name')->unique() + ->string('password') + ->integer('permission') + ; + }); + + // Insert initial data. + $manager->create('users', array( + array( + 'name' => 'admin', + 'password' => '$2y$10$VzBQqiwnhG5zc2.MQmmW4ORcPW6FE7SLhPr1VBV2ubn5zJoesnmli', + 'permission' => \Bean\User::ADMIN, + ), + )); + + trigger_error( + 'no existing database, creating default user (admin:admin)', + E_USER_WARNING + ); + } + + $manager->_file = $file; + return $manager; + } + + /** + * + */ + function createTable($name, $callback) + { + $result = parent::createTable($name, $callback); + $this->_save(); + return $result; + } + + /** + * + */ + function deleteTable($name) + { + $result = parent::deleteTable($name); + $this->_save(); + return $result; + } + + /** + * + */ + function create($table, array $entries) + { + $result = parent::create($table, $entries); + $this->_save(); + return $result; + } + + /** + * + */ + function delete($table, array $filter) + { + $result = parent::delete($table, $filter); + $this->_save(); + return $result; + } + + /** + * + */ + function update($table, array $filter, array $properties) + { + $result = parent::update($table, $filter, $properties); + $this->_save(); + return $result; + } + + /** + * + */ + private $_file; + + /** + * + */ + private function _save() + { + if (!$this->_file) + { + return; + } + + $bytes = @file_put_contents( + $this->_file, + json_encode($this->getState()) + ); + if (!$bytes) + { + trigger_error( + 'could not write the database', + E_USER_ERROR + ); + } + } +}