From c73dcb2280cc3512d89d39e36f8c29c4bab89e96 Mon Sep 17 00:00:00 2001 From: Andrey Kutejko Date: Sun, 24 Aug 2014 20:10:43 +0300 Subject: [PATCH] rework auth and admin apps. try to separate from legacy orm. WIP --- ipf/admin/app.php | 133 +++-- ipf/admin/commands/syncperms.php | 19 +- ipf/admin/{form.php => formlayout.php} | 21 - ipf/{auth => admin}/forms/changepassword.php | 12 +- ipf/{auth => admin}/forms/login.php | 12 +- ipf/admin/legacymodel.php | 229 +++++++++ ipf/admin/model.php | 466 +++++------------- ipf/admin/modelinline.php | 11 +- ipf/admin/models/AdminLog.php | 25 +- ipf/admin/templates/admin/change.html | 18 +- ipf/admin/templates/admin/changepassword.html | 9 +- ipf/admin/templates/admin/delete.html | 27 +- ipf/admin/templates/admin/index.html | 8 +- ipf/admin/templates/admin/items.html | 25 +- ipf/admin/views.php | 269 ++-------- ipf/application.php | 2 +- ipf/auth/admin.php | 379 ++++++++++++++ ipf/auth/app.php | 74 +-- ipf/auth/middleware.php | 2 +- .../20140102000000_create_auth_tables.php | 23 + ipf/auth/models.php | 129 +++++ ipf/auth/models.yml | 146 ------ ipf/auth/models/Permission.php | 10 - ipf/auth/models/Role.php | 73 --- ipf/auth/models/RolePermission.php | 6 - ipf/auth/models/User.php | 271 ---------- ipf/auth/models/UserPermission.php | 6 - ipf/auth/models/UserRole.php | 6 - ipf/auth/models/_generated/BasePermission.php | 39 -- ipf/auth/models/_generated/BaseRole.php | 38 -- .../models/_generated/BaseRolePermission.php | 37 -- ipf/auth/models/_generated/BaseUser.php | 47 -- .../models/_generated/BaseUserPermission.php | 37 -- ipf/auth/models/_generated/BaseUserRole.php | 37 -- 34 files changed, 1138 insertions(+), 1508 deletions(-) rename ipf/admin/{form.php => formlayout.php} (73%) rename ipf/{auth => admin}/forms/changepassword.php (73%) rename ipf/{auth => admin}/forms/login.php (75%) create mode 100644 ipf/admin/legacymodel.php create mode 100644 ipf/auth/admin.php create mode 100644 ipf/auth/migrations/20140102000000_create_auth_tables.php delete mode 100644 ipf/auth/models.yml delete mode 100644 ipf/auth/models/Permission.php delete mode 100644 ipf/auth/models/Role.php delete mode 100644 ipf/auth/models/RolePermission.php delete mode 100644 ipf/auth/models/User.php delete mode 100644 ipf/auth/models/UserPermission.php delete mode 100644 ipf/auth/models/UserRole.php delete mode 100644 ipf/auth/models/_generated/BasePermission.php delete mode 100644 ipf/auth/models/_generated/BaseRole.php delete mode 100644 ipf/auth/models/_generated/BaseRolePermission.php delete mode 100644 ipf/auth/models/_generated/BaseUser.php delete mode 100644 ipf/auth/models/_generated/BaseUserPermission.php delete mode 100644 ipf/auth/models/_generated/BaseUserRole.php diff --git a/ipf/admin/app.php b/ipf/admin/app.php index 5221a33..30a6365 100644 --- a/ipf/admin/app.php +++ b/ipf/admin/app.php @@ -38,26 +38,72 @@ class IPF_Admin_App extends IPF_Application return new IPF_HTTP_Response($html); } - public static function loadAllModels() + private static $appComponents = array(); + + public static function applicationComponents($app) { - foreach (IPF_Project::getInstance()->appList() as $appname => $app) - foreach (IPF_Legacy_ORM_App::appModelList($app) as $modelName) - new $modelName; + if (!array_key_exists($app->slug(), self::$appComponents)) { + $components = array(); + + if (is_file($app->getPath().'/admin.php')) { + $list = require_once $app->getPath().'/admin.php'; + foreach ($list as $c) { + $component = is_string($c) ? new $c : $c; + $component->app = $app; + $components[] = $component; + } + } + + // legacy ORM + foreach (IPF_Legacy_ORM_App::appModelList($app) as $m) { + new $m; // autoload + $ma = IPF_Admin_Model::getModelAdmin($m); + if ($ma) { + $ma->app = $app; + $components[] = $ma; + } + } + + self::$appComponents[$app->slug()] = $components; + } + return self::$appComponents[$app->slug()]; } - static function checkAdminAuth($request) + public static function ensureUserIsStaff($request) { - $ok = true; if ($request->user->isAnonymous()) - $ok = false; - elseif ( (!$request->user->is_staff) && (!$request->user->is_superuser) ) - $ok = false; + throw new IPF_Admin_LoginRequired; + + if (!$request->user->is_staff && !$request->user->is_superuser) + throw new IPF_Admin_LoginRequired; + } + + public static function isAccessible($request, $component, $requiredPermissions) + { + if (count(array_diff($requiredPermissions, $component->getPerms($request)))) + return false; + + if ($request->user->is_superuser || !self::ArePermissionsEnabled()) + return true; + + $authPermissions = \PFF\Arr($requiredPermissions) + ->map('sprintf', '%s|%s|%s', get_class($component->app), $component->slug(), \PFF\Symbol::_()) + ->arr(); + + return $request->user->can($authPermissions); + } + + public static function getComponent($request, $requiredPermissions) + { + self::ensureUserIsStaff($request); + + $component = self::getComponentBySlugs($request->params[1], $request->params[2]); - if (!$ok) - return new IPF_HTTP_Response_Redirect(IPF_HTTP_URL::urlForView('IPF_Admin_Views_Login')); + if (!IPF_Admin_App::isAccessible($request, $component, $requiredPermissions)) + throw new IPF_Admin_AccessDenied; - self::loadAllModels(); - return true; + $component->request = $request; + return $component; } static function appByModel($model) @@ -69,45 +115,22 @@ class IPF_Admin_App extends IPF_Application return null; } - static function GetAppModelFromSlugs($lapp, $lmodel) + public static function getApplicationBySlug($slug) { - foreach (IPF_Project::getInstance()->appList() as $app) { - if ($app->getSlug() == $lapp) { - foreach (IPF_Legacy_ORM_App::appModelList($app) as $m) { - if (strtolower($m) == $lmodel) - return array('app' => $app, 'modelname' => $m); - } - } - } - return null; + foreach (IPF_Project::getInstance()->appList() as $app) + if ($app->slug() == $slug) + return $app; + throw new IPF_HTTP_Error404; } - static function GetAdminModelPermissions($adminModel, $request, $lapp, $lmodel) + public static function getComponentBySlugs($appSlug, $componentSlug) { - $adminPerms = $adminModel->getPerms($request); - - if (!count($adminPerms)) - return false; - - $am = self::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am === null) - return false; - - $app = $am['app']; - $m = $am['modelname']; - - if ($m !== $adminModel->modelName) - return false; - - $perms = array(); - - foreach (IPF_Auth_App::checkPermissions($request, $app, $m, $adminPerms) as $permName=>$permValue) { - if ($permValue) - $perms[] = $permName; + $app = self::getApplicationBySlug($appSlug); + foreach (self::applicationComponents($app) as $component) { + if ($component->slug() == $componentSlug) + return $component; } - - return $perms; + throw new IPF_HTTP_Error404; } public function commands() @@ -118,3 +141,19 @@ class IPF_Admin_App extends IPF_Application } } +class IPF_Admin_LoginRequired extends IPF_Router_Shortcut +{ + public function response($request) + { + return new IPF_HTTP_Response_Redirect(IPF_HTTP_URL::urlForView('IPF_Admin_Views_Login')); + } +} + +class IPF_Admin_AccessDenied extends IPF_Router_Shortcut +{ + public function response($request) + { + return new IPF_HTTP_Response_NotFound($request); + } +} + diff --git a/ipf/admin/commands/syncperms.php b/ipf/admin/commands/syncperms.php index 7940096..45f4413 100644 --- a/ipf/admin/commands/syncperms.php +++ b/ipf/admin/commands/syncperms.php @@ -9,19 +9,14 @@ class IPF_Admin_Command_SyncPerms { print "Create/Update permissions from model classes\n"; - IPF_Admin_App::loadAllModels(); - print "COLLECTED PERMISSIONS:\n"; $permissions = array(); foreach (IPF_Project::getInstance()->appList() as $appname => $app) { - foreach (IPF_Legacy_ORM_App::appModelList($app) as $modelName) { - $adminModel = IPF_Admin_Model::getModelAdmin($modelName); - if ($adminModel) { - foreach ($adminModel->getPerms(null) as $permName) { - $name = get_class($app).'|'.$modelName.'|'.$permName; - $permissions[$name] = array($app, $modelName, $permName); - print ' '.$name."\n"; - } + foreach (IPF_Admin_App::applicationComponents($app) as $component) { + foreach ($component->getPerms(null) as $permName) { + $name = get_class($app).'|'.$component->slug().'|'.$permName; + $permissions[$name] = array($app, $component, $permName); + print ' '.$name."\n"; } } } @@ -50,13 +45,13 @@ class IPF_Admin_Command_SyncPerms foreach ($toAdd as $name) { $app = $permissions[$name][0]; - $admin = IPF_Admin_Model::getModelAdmin($permissions[$name][1]); + $component = $permissions[$name][1]; \PFF\Container::databaseQuery() ->insertInto('auth_permission') ->values(array( 'name' => $name, - 'title' => $app->getTitle().' | '.$admin->verbose_name().' | '.ucfirst($permissions[$name][2]), + 'title' => $app->getTitle().' | '.$component->slug().' | '.ucfirst($permissions[$name][2]), ))->execute(); } } diff --git a/ipf/admin/form.php b/ipf/admin/formlayout.php similarity index 73% rename from ipf/admin/form.php rename to ipf/admin/formlayout.php index 3f7330a..47690e6 100644 --- a/ipf/admin/form.php +++ b/ipf/admin/formlayout.php @@ -2,27 +2,6 @@ use \PFF\HtmlBuilder\Tag as Tag; - -class IFP_Admin_ModelForm extends IPF_Form_Model -{ - public function unescape($html) - { - return new IPF_Template_SafeString($html, true); - } - - public function render() - { - return $this->renderLayout(new IPF_Admin_Form_Layout, false); - } - - public static function GetFormForModel($model, $data=null, $extra=array(), $label_suffix=null) - { - $extra['model'] = $model; - return new self($data, $extra, $label_suffix); - } -} - - class IPF_Admin_Form_Layout extends IPF_Form_LayoutAdapter { public function startForm($form) diff --git a/ipf/auth/forms/changepassword.php b/ipf/admin/forms/changepassword.php similarity index 73% rename from ipf/auth/forms/changepassword.php rename to ipf/admin/forms/changepassword.php index 5162647..bff9094 100644 --- a/ipf/auth/forms/changepassword.php +++ b/ipf/admin/forms/changepassword.php @@ -1,6 +1,6 @@ renderLayout(new IPF_Admin_Form_Layout, false); + } + + public function unescape($html) + { + return new IPF_Template_SafeString($html, true); + } } diff --git a/ipf/auth/forms/login.php b/ipf/admin/forms/login.php similarity index 75% rename from ipf/auth/forms/login.php rename to ipf/admin/forms/login.php index 405e5d0..37a4ea8 100644 --- a/ipf/auth/forms/login.php +++ b/ipf/admin/forms/login.php @@ -1,6 +1,6 @@ renderLayout(new IPF_Admin_Form_Layout, false); + } + + public function unescape($html) + { + return new IPF_Template_SafeString($html, true); + } } diff --git a/ipf/admin/legacymodel.php b/ipf/admin/legacymodel.php new file mode 100644 index 0000000..aaad49f --- /dev/null +++ b/ipf/admin/legacymodel.php @@ -0,0 +1,229 @@ +modelName = $modelName; + } + + public function slug() + { + return strtolower($this->modelName); + } + + private function table() + { + return IPF_ORM::getTable($this->modelName); + } + + private function query($searchValue) + { + if (method_exists($this->modelName, 'ordering')) { + $m = new $this->modelName; + $ord = $m->ordering(); + } elseif ($this->table()->getOrdering()) { + $ord = implode(', ', $this->table()->getOrdering()); + } elseif ($this->table()->hasTemplate('IPF_ORM_Template_Orderable')) { + $ord = $this->table()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + } else { + $ord = '1 desc'; + } + + $q = IPF_ORM_Query::create()->from($this->modelName)->orderby($ord); + + if ($searchValue) { + $wh = array(); + $whv = array(); + foreach ($this->_searchFields() as $f) { + $wh[] = $f.' like ?'; + $whv[] = '%'.$searchValue.'%'; + } + $q->addWhere($wh, $whv); + } + + return $q; + } + + public function ListItemsQuery($searchValue, $page, $pageSize) + { + $idColumn = $this->table()->getIdentifier(); + + $result = array(); + foreach ($this->query($searchValue)->limit($pageSize)->offset(($page - 1) * $pageSize)->execute() as $o) { + $id = $o->__get($idColumn); + $result[$id] = $o; + } + return $result; + } + + public function ListItemsQueryCount($searchValue) + { + return $this->query($searchValue)->count(); + } + + public function getObjectByID($id) + { + return $this->table()->find($id); + } + + public function searcheable() + { + return count($this->_searchFields()) > 0; + } + + protected function _searchFields() + { + return array(); + } + + public function list_display() + { + return $this->table()->getColumnNames(); + } + + public function renderCell($object, $column) + { + $value = $object->$column; + switch ($object->getTable()->getTypeOf($column)) { + case 'boolean': + if ($value) + return 'True'; + else + return 'False'; + case 'timestamp': + return htmlspecialchars(IPF_Utils::formatDate($value), ENT_COMPAT, 'UTF-8'); + default: + return htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); + } + } + + protected function columnTitle($column) + { + $columns = $this->table()->getColumns(); + if (array_key_exists($column, $columns) && array_key_exists('verbose', $columns[$column])) + return $columns[$column]['verbose']; + else + return parent::columnTitle($column); + } + + public function _orderable() + { + return $this->_orderableColumn() !== null; + } + + public function _orderableColumn() + { + if (method_exists($this, 'list_order')) + return $this->list_order(); + elseif ($this->table()->hasTemplate('IPF_ORM_Template_Orderable')) + return $this->table()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); + else + return null; + } + + public function reorder($ids) + { + if (!$this->_orderable()) + return false; + + $ord_field = $this->_orderableColumn(); + + $table = IPF_ORM::getTable($this->modelName); + $conn = $table->getConnection(); + + $idColumn = $table->getIdentifier(); + if (is_array($idColumn)) + $idColumn = $idColumn[0]; + + $questions = str_repeat('?,', count($ids)-1) . '?'; + $query = 'SELECT ' . $conn->quoteIdentifier($ord_field) . + ' FROM ' . $conn->quoteIdentifier($table->getTableName()) . + ' WHERE ' . $conn->quoteIdentifier($idColumn) . ' IN (' . $questions . ')' . + ' ORDER BY ' . $conn->quoteIdentifier($ord_field); + $ords = $conn->fetchColumn($query, $ids); + + $i = 0; + foreach ($ids as $id) { + $item = $table->find($id); + $item[$ord_field] = $ords[$i]; + $item->save(); + $i++; + } + + return true; + } + + /* edit */ + + protected function _getForm($model, $data) + { + if ($model) { + // edit + if (!$data) + $data = $this->getFormData($model); + } else { + // add + $model = new $this->modelName; + } + + $extra = array( + 'user_fields' => $this->fields(), + 'model' => $model, + ); + + return new IPF_Form_Model($data, $extra); + } + + public function saveObject($form, $model) + { + $model = $form->save(); + $idColumn = $this->table()->getIdentifier(); + return array($model->$idColumn, $model); + } + + public function deleteObject($model) + { + $model->delete(); + } + + public function fields() + { + return null; + } + + public function getFormData($o) + { + $data = $o->getData(); + foreach ($o->getTable()->getRelations() as $rname => $rel) { + $fields = $this->fields(); + if (!$fields || in_array($rname, $fields)) { + if ($rel->getType() == IPF_ORM_Relation::MANY_AGGREGATE) { + $data[$rname] = array(); + foreach ($rel->fetchRelatedFor($o) as $ri) { + $data[$rname][] = $ri->pk(); + } + } + } + } + return $data; + } +} + diff --git a/ipf/admin/model.php b/ipf/admin/model.php index bd3b1ed..9a9fba3 100644 --- a/ipf/admin/model.php +++ b/ipf/admin/model.php @@ -358,106 +358,45 @@ class DateHierarchyListFilter extends BaseListFilter { } } -class IPF_Admin_ModelListener +abstract class IPF_Admin_Component { - public function beforeEdit($o) - { - $this->beforeChange($o); - } - - public function beforeAdd($o) - { - $this->beforeChange($o); - } - - public function beforeChange($o) - { - } - - public function afterEdit($o) - { - $this->afterChange($o); - } - - public function afterAdd($o) - { - $this->afterChange($o); - } - - public function afterChange($o) - { - } -} - -class IPF_Admin_Model -{ - static $models = array(); - static $handlers = array(); - - public static function register($classModel, $classAdmin) - { - $ma = new $classAdmin($classModel); - self::$models[$classModel] = $ma; - foreach (\PFF\Arr::get(self::$handlers, $classModel, array()) as $action) { - call_user_func($action, $ma); - } - unset(self::$handlers[$classModel]); - } - - public static function isModelRegister($classModel) - { - return array_key_exists($classModel, self::$models); - } - - public static function getModelAdmin($classModel) - { - if (array_key_exists($classModel, self::$models)) { - $ma = self::$models[$classModel]; - $ma->setUp(); - return $ma; - } - return null; - } - - public static function on($classModel, $action) - { - if (array_key_exists($classModel, self::$models)) { - call_user_func($action, self::$models[$classModel]); - } else { - \PFF\Arr::pushToKey(self::$handlers, $classModel, $action); - } - } - - var $modelName = null; - var $model = null; var $inlineInstances = array(); var $perPage = 50; - public $hidden = false; - public $modelListeners = array(); - public function __construct($modelName) - { - $this->modelName = $modelName; - } + public $app = null, $request = null; public function verbose_name() { return IPF_Utils::humanTitle($this->modelName); } + public function slug() + { + $slug = get_class($this); + $slug = preg_replace('/^Admin([A-Z])/', '\1', $slug); + $slug = preg_replace('/Admin$/', '', $slug); + $slug = preg_replace('/([a-z0-9])([A-Z0-9])/', '\1-\2', $slug); + $slug = preg_replace('/\W+/', '-', $slug); + return strtolower($slug); + } + public function titleList() { return $this->verbose_name().' List'; } public function titleAdd() { return 'Add ' . $this->verbose_name(); } public function titleEdit() { return 'Edit ' . $this->verbose_name(); } public function titleDelete() { return 'Delete ' . $this->verbose_name(); } - public function setUp() + public function getPerms($request) { - $this->model = new $this->modelName; + return array('view', 'add', 'change', 'delete'); } - public function getPerms($request) + public function isAccessible($what, $request=null) { - return array('view', 'add', 'change', 'delete'); + if (!$request) + $request = $this->request; + if (!$request) + throw new IPF_Exception('No request.'); + return IPF_Admin_App::isAccessible($request, $this, $what); } protected function context($request) @@ -467,7 +406,13 @@ class IPF_Admin_Model protected function renderToResponse($template, $context, $request) { - $context = array_merge($this->context($request), $context); + $context = array_merge( + array( + 'component' => $this, + 'app' => $this->app, + ), + $this->context($request), + $context); return IPF_Admin_App::RenderToResponse($template, $context, $request); } @@ -507,11 +452,6 @@ class IPF_Admin_Model { } - public function fields() - { - return null; - } - public function inlines() { return null; @@ -525,49 +465,47 @@ class IPF_Admin_Model return true; } + public abstract function list_display(); + + protected function columnTitle($column) + { + return IPF_Utils::humanTitle($column); + } + public function ListItemsHeader() { $this->header = array(); - if (method_exists($this, 'list_display')) - $this->names = $this->list_display(); - else - $this->names = $this->model->getTable()->getColumnNames(); - - $columns = $this->model->getTable()->getColumns(); + $this->names = $this->list_display(); foreach ($this->names as $name) { if (is_array($name)) { list($name, $title) = $name; - } elseif (array_key_exists($name, $columns) && array_key_exists('verbose', $columns[$name])) { - $title = $columns[$name]['verbose']; } else { - $title = IPF_Utils::humanTitle($name); + $title = $this->columnTitle($name); } - $this->header[$name] = new IPF_Template_ContextVars(array( - 'title' => $title, - 'name' => $name, - 'sortable' => null, - )); + $this->header[$name] = array( + 'title' => $title, + 'name' => $name, + ); } return $this->header; } - public function ListItemsQuery() + public abstract function ListItemsQuery($searchValue, $page, $pageSize); + public abstract function ListItemsQueryCount($searchValue); + public abstract function getObjectByID($id); + public abstract function saveObject($form, $object); + public abstract function deleteObject($object); + + public function searcheable() { - if (method_exists($this->model,'ordering')) { - $ord = $this->model->ordering(); - } elseif ($this->model->getTable()->getOrdering()) { - $ord = implode(', ', $this->model->getTable()->getOrdering()); - } elseif ($this->model->getTable()->hasTemplate('IPF_ORM_Template_Orderable')) { - $ord = $this->model->getTable()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); - } else { - $ord = '1 desc'; - } - $this->q = IPF_ORM_Query::create()->from($this->modelName)->orderby($ord); + return false; } - public function ListRow($o) + public abstract function renderCell($object, $column); + + public function ListRow($o, $id) { $row = array(); @@ -576,27 +514,15 @@ class IPF_Admin_Model if (method_exists($this,$listMethod)) { $str = $this->$listMethod($o); } else { - $t = $o->getTable()->getTypeOf($h['name']); - $str = $o->$h['name']; - switch ($t) { - case 'boolean': - if ($str) - $str = 'True'; - else - $str = 'False'; - break; - case 'timestamp': - $str = IPF_Utils::formatDate($str); - break; - } + $str = $this->renderCell($o, $h['name']); } $row[$h['name']] = $str; } - $this->linksRow($row, $o); + $this->linksRow($row, $o, $id); return $row; } - protected function linksRow(&$row, $o) + protected function linksRow(&$row, $o, $id) { if (method_exists($this, 'list_display_links')) { $links_display = $this->list_display_links(); @@ -607,33 +533,25 @@ class IPF_Admin_Model foreach ($row as $name => &$v) { if ($links_display) { if (array_search($name, $links_display) !== false) - $v = ''.$v.''; + $v = ''.$v.''; } else { if ($i == 1) - $v = ''.$v.''; + $v = ''.$v.''; $i++; } } } - protected function UrlForResult($o) - { - return $o->__get($this->model->getTable()->getIdentifier()).'/'; - } - - protected function _getForm($model_obj, $data, $extra) - { - return IFP_Admin_ModelForm::GetFormForModel($model_obj, $data, $extra); - } + protected abstract function _getForm($obj, $data); - protected function _getEditForm($model_obj, $data, $extra) + protected function _getEditForm($model_obj, $data) { - return $this->_getForm($model_obj, $data, $extra); + return $this->_getForm($model_obj, $data); } - protected function _getAddForm($model_obj, $data, $extra) + protected function _getAddForm($model_obj, $data) { - return $this->_getForm($model_obj, $data, $extra); + return $this->_getForm($model_obj, $data); } protected function _getListTemplate() @@ -651,42 +569,6 @@ class IPF_Admin_Model return 'admin/change.html'; } - protected function _beforeEdit($o) - { - foreach ($this->modelListeners as $l) - $l->beforeEdit($o); - $this->_beforeChange($o); - } - - protected function _beforeAdd($o) - { - foreach ($this->modelListeners as $l) - $l->beforeAdd($o); - $this->_beforeChange($o); - } - - protected function _beforeChange($o) - { - } - - protected function _afterEdit($o) - { - foreach ($this->modelListeners as $l) - $l->afterEdit($o); - $this->_afterChange($o); - } - - protected function _afterAdd($o) - { - foreach ($this->modelListeners as $l) - $l->afterAdd($o); - $this->_afterChange($o); - } - - protected function _afterChange($o) - { - } - protected function extraMedia($form) { return array( @@ -701,39 +583,27 @@ class IPF_Admin_Model } // Views Function - public function AddItem($request, $lapp, $lmodel) + public function AddItem($request) { - $perms = IPF_Admin_App::GetAdminModelPermissions($this, $request, $lapp, $lmodel); - - if ($perms === false || !in_array('view', $perms) || !in_array('add', $perms)) - return new IPF_HTTP_Response_NotFound($request); - $errors = false; if ($request->method == 'POST') { - $this->_beforeAdd(new $this->model()); - $data = $request->POST+$request->FILES; - $form = $this->_getAddForm($this->model, $data, array('user_fields'=>$this->fields())); + $form = $this->_getAddForm(null, $request->POST + $request->FILES); $this->_setupAddForm($form); - $this->setInlines($this->model, $data); - - $validForm = $form->isValid(); - $validInlines = $this->isValidInlines(); - if ($validForm && $validInlines) { - $item = $form->save(); - $this->saveInlines($item); - AdminLog::logAction($request, $item, AdminLog::ADDITION); - $this->_afterAdd($item); + + if ($form->isValid()) { + list($id, $object) = $this->saveObject($form, null); + + AdminLog::logAction($request->user, AdminLog::ADDITION, (string)$object, IPF_HTTP_URL::urlForView('IPF_Admin_Views_EditItem', array($this->app->slug(), $this->slug(), $id))); + $url = @$request->POST['ipf_referrer']; - if ($url=='') - $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($lapp, $lmodel)); + if (!$url) + $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($this->app->slug(), $this->slug())); return new IPF_HTTP_Response_Redirect($url); } $errors = true; } else { - $form = $this->_getAddForm($this->model,null,array('user_fields'=>$this->fields())); + $form = $this->_getAddForm(null, null); $this->_setupAddForm($form); - $data = array(); - $this->setInlines($this->model); } $extraMedia = $this->extraMedia($form); @@ -743,169 +613,122 @@ class IPF_Admin_Model 'page_title'=>$this->titleAdd(), 'classname'=>$this->verbose_name(), 'form' => $form, + 'form_html' => $form->renderLayout(new IPF_Admin_Form_Layout), 'extra_js' => $extraMedia['js'], 'extra_css' => $extraMedia['css'], 'inlineInstances'=>$this->inlineInstances, 'errors' => $errors, - 'lapp'=>$lapp, - 'perms'=>$perms, - 'lmodel'=>$lmodel, 'objecttools' => array(), ); return $this->renderToResponse($this->_getAddTemplate(), $context, $request); } - public function DeleteItem($request, $lapp, $lmodel, $o) + public function DeleteItem($request, $id) { - $perms = IPF_Admin_App::GetAdminModelPermissions($this, $request, $lapp, $lmodel); - - if ($perms === false || !in_array('view', $perms) || !in_array('delete', $perms)) - return new IPF_HTTP_Response_NotFound($request); + $object = $this->getObjectByID($id); + if (!$object) + throw new IPF_HTTP_Error404; + + if ($request->method == 'POST') { + AdminLog::logAction($request->user, AdminLog::DELETION, (string)$object); + + $this->deleteObject($object); - if ($request->method == 'POST') - { - AdminLog::logAction($request, $o, AdminLog::DELETION); - $o->delete(); $url = @$request->POST['ipf_referrer']; - if ($url=='') - $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($lapp, $lmodel)); + if (!$url) + $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($this->app->slug(), $this->slug())); return new IPF_HTTP_Response_Redirect($url); } + $context = array( - 'page_title'=>$this->titleDelete(), - 'classname'=>$this->verbose_name(), - 'object'=>$o, - 'lapp'=>$lapp, - 'lmodel'=>$lmodel, - 'affected'=>array(), - 'ipf_referrer'=>@$request->GET['ipf_referrer'], + 'page_title' => $this->titleDelete(), + 'classname' => $this->verbose_name(), + 'object' => $object, + 'object_id' => $id, + 'ipf_referrer' => @$request->GET['ipf_referrer'], ); return $this->renderToResponse('admin/delete.html', $context, $request); } - public function EditItem($request, $lapp, $lmodel, $o) + public function EditItem($request, $id) { - $perms = IPF_Admin_App::GetAdminModelPermissions($this, $request, $lapp, $lmodel); - - if ($perms === false || !in_array('view', $perms)) - return new IPF_HTTP_Response_NotFound($request); + $object = $this->getObjectByID($id); + if (!$object) + throw new IPF_HTTP_Error404; $errors = false; if ($request->method == 'POST') { - if (!in_array('change', $perms)) - return new IPF_HTTP_Response_NotFound($request); - - $this->_beforeEdit($o); - $data = $request->POST+$request->FILES; - $form = $this->_getEditForm($o, $data, array('user_fields'=>$this->fields())); + $form = $this->_getEditForm($object, $request->POST + $request->FILES); $this->_setupEditForm($form); - $this->setInlines($o, $data); - - $validForm = $form->isValid(); - $validInlines = $this->isValidInlines(); - if ($validForm && $validInlines) { - $item = $form->save(); - $this->saveInlines($item); - AdminLog::logAction($request, $item, AdminLog::CHANGE); - $this->_afterEdit($item); + + if ($form->isValid()) { + list($id, $object) = $this->saveObject($form, $object); + + AdminLog::logAction($request->user, AdminLog::CHANGE, (string)$object, IPF_HTTP_URL::urlForView('IPF_Admin_Views_EditItem', array($this->app->slug(), $this->slug(), $id))); + $url = @$request->POST['ipf_referrer']; - if ($url=='') - $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($lapp, $lmodel)); + if (!$url) + $url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($this->app->slug(), $this->slug())); + return new IPF_HTTP_Response_Redirect($url); } $errors = true; } else { - $data = $o->getData(); - foreach ($o->getTable()->getRelations() as $rname => $rel) { - $fields = $this->fields(); - if (!$fields || in_array($rname, $fields)) { - if ($rel->getType() == IPF_ORM_Relation::MANY_AGGREGATE) { - $data[$rname] = array(); - foreach ($rel->fetchRelatedFor($o) as $ri) { - $data[$rname][] = $ri->pk(); - } - } - } - } - $form = $this->_getEditForm($o, $data, array('user_fields'=>$this->fields())); + $form = $this->_getEditForm($object, null); $this->_setupEditForm($form); - $this->setInlines($o); } - $objecttools = $this->objectTools($o); + $objecttools = $this->objectTools($object); $extraMedia = $this->extraMedia($form); $context = array( 'mode'=>'change', 'page_title'=>$this->titleEdit(), 'classname'=>$this->verbose_name(), - 'object'=>$o, + 'object' => $object, + 'object_id' => $id, 'form' => $form, + 'form_html' => $form->renderLayout(new IPF_Admin_Form_Layout), 'extra_js' => $extraMedia['js'], 'extra_css' => $extraMedia['css'], 'inlineInstances'=>$this->inlineInstances, 'errors' => $errors, - 'lapp'=>$lapp, - 'perms'=>$perms, - 'lmodel'=>$lmodel, 'objecttools' => $objecttools, ); return $this->renderToResponse($this->_getChangeTemplate(), $context, $request); } - public function ListItems($request, $lapp, $lmodel) + public function ListItems($request) { - $perms = IPF_Admin_App::GetAdminModelPermissions($this, $request, $lapp, $lmodel); + $searchValue = @$request->GET['q']; + $this->filters = array(); + // $this->_GetFilters($request); - if ($perms === false || !in_array('view', $perms)) - return new IPF_HTTP_Response_NotFound($request); + $currentPage = (int)@$request->GET['page']; + if (!$currentPage) + $currentPage = 1; - $this->ListItemsQuery(); - $this->_GetFilters($request); - $this->_ListSearchQuery($request); - $this->_ListFilterQuery($request); - $this->ListItemsHeader(); + $count = $this->ListItemsQueryCount($searchValue); + $objects = $this->ListItemsQuery($searchValue, $currentPage, $this->perPage); - $currentPage = (int)@$request->GET['page']; + $this->ListItemsHeader(); - $url = ''; - foreach ($request->GET as $k=>$v){ - if ($k=='page') - continue; - if ($url=='') - $url = '?'; - else - $url .= '&'; - $url .= $k.'='.$v; - } - if ($url=='') - $pager_url = '?page={%page_number}'; - else - $pager_url = $url.'&page={%page_number}'; - - $pager = new IPF_ORM_Pager_LayoutArrows( - new IPF_ORM_Pager($this->q, $currentPage, $this->perPage), - new IPF_ORM_Pager_Range_Sliding(array('chunk' => 10)), - $pager_url - ); - $pager->setTemplate('{%page} '); - $pager->setSelectedTemplate('{%page} '); - $objects = $pager->getPager()->execute(); + $pagerLayout = new IPF_Pager_Layout; + $pages = $pagerLayout->layout($currentPage, ceil($count / $this->perPage)); $context = array( 'orderable'=>$this->_orderable(), 'page_title'=>$this->titleList(), 'header'=>$this->header, - 'objects'=>$objects, - 'pager'=>$pager, + 'objects' => $objects, + 'count' => $count, + 'pages' => $pages, + 'current_page' => $currentPage, 'classname'=>$this->verbose_name(), 'title_add'=>$this->titleAdd(), - 'perms'=>$perms, 'filters'=>$this->filters, - 'is_search' => $this->_isSearch(), - 'search_value' => $this->search_value, - 'lapp'=>$lapp, - 'lmodel'=>$lmodel, + 'is_search' => $this->searcheable(), + 'search_value' => $searchValue, ); return $this->renderToResponse($this->_getListTemplate(), $context, $request); } @@ -917,30 +740,6 @@ class IPF_Admin_Model } } - protected function _isSearch() - { - return method_exists($this,'_searchFields'); - } - - protected function _ListSearchQuery($request) - { - $this->search_value = null; - if (!$this->_isSearch()) - return; - $fields = $this->_searchFields(); - $this->search_value = @$request->GET['q']; - if ($this->search_value!=''){ - $wh = ''; - $whv = array(); - foreach ($fields as $f){ - if ($wh!='') $wh.=' or '; - $wh.= $f.' like ?'; - $whv[] = '%'.$this->search_value.'%'; - } - $this->q->addWhere($wh,$whv); - } - } - protected function _GetFilters($request) { $this->filters = array(); @@ -991,17 +790,12 @@ class IPF_Admin_Model public function _orderable() { - return $this->_orderableColumn() !== null; + return false; } - public function _orderableColumn() + public function reorder($ids) { - if (method_exists($this, 'list_order')) - return $this->list_order(); - elseif ($this->model->getTable()->hasTemplate('IPF_ORM_Template_Orderable')) - return $this->model->getTable()->getTemplate('IPF_ORM_Template_Orderable')->getColumnName(); - else - return null; + throw new IPF_Exception('Reordering is not implemented.'); } } diff --git a/ipf/admin/modelinline.php b/ipf/admin/modelinline.php index 42eb5d2..0baf64d 100644 --- a/ipf/admin/modelinline.php +++ b/ipf/admin/modelinline.php @@ -21,7 +21,11 @@ abstract class IPF_Admin_ModelInline public function getApplication() { - return IPF_Admin_App::appByModel($this->getModelName()); + foreach (IPF_Project::getInstance()->appList() as $app) + foreach (IPF_Legacy_ORM_App::appModelList($app) as $model) + if ($model == $this->getModelName()) + return $app; + return null; } function getAddNum() @@ -81,9 +85,10 @@ abstract class IPF_Admin_ModelInline return true; } - protected function _getForm($model_obj, $data, $extra) + protected function _getForm($model, $data, $extra) { - return IFP_Admin_ModelForm::GetFormForModel($model_obj, $data, $extra); + $extra['model'] = $model; + return new IPF_Form_Model($data, $extra); } function getFkName() diff --git a/ipf/admin/models/AdminLog.php b/ipf/admin/models/AdminLog.php index c2c0adc..3f8fa00 100644 --- a/ipf/admin/models/AdminLog.php +++ b/ipf/admin/models/AdminLog.php @@ -6,27 +6,14 @@ class AdminLog extends BaseAdminLog const CHANGE = 2; const DELETION = 3; - public static function logAction($request, $object, $action_flag, $object_url=null, $message='') + public static function logAction($who, $action, $repr, $url=null) { $log = new AdminLog; - $log->username = $request->user->username; - $log->user_id = $request->user->id; - - $log->object_id = (int)$object[$object->getTable()->getIdentifier()]; - $log->object_class = get_class($object); - $log->object_repr = (string)$object; - - if (!$object_url) { - $app = IPF_Admin_App::appByModel($log->object_class); - if ($app) - $object_url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_EditItem', array($app->getSlug(), strtolower($log->object_class), $log->object_id)); - } - - $log->object_url = $object_url; - - $log->action_flag = $action_flag; - $log->change_message = $message; - + $log->username = $who->username; + $log->user_id = $who->id; + $log->object_repr = $repr; + $log->object_url = $url; + $log->action_flag = $action; $log->save(); } diff --git a/ipf/admin/templates/admin/change.html b/ipf/admin/templates/admin/change.html index 9929925..05938cf 100644 --- a/ipf/admin/templates/admin/change.html +++ b/ipf/admin/templates/admin/change.html @@ -10,7 +10,13 @@ {block bodyclass}change-form{/block} -{block breadcrumbs}{/block} +{block breadcrumbs} + +{/block} {block content}
@@ -31,7 +37,7 @@ {/if}
{block form} - {$form->render()} + {$form_html|safe} {/block}
{if $inlineInstances} @@ -40,7 +46,7 @@ diff --git a/ipf/admin/templates/admin/changepassword.html b/ipf/admin/templates/admin/changepassword.html index e43341f..8386b44 100644 --- a/ipf/admin/templates/admin/changepassword.html +++ b/ipf/admin/templates/admin/changepassword.html @@ -7,7 +7,14 @@ {block bodyclass}change-form{/block} -{block breadcrumbs}{/block} +{block breadcrumbs} + +{/block} {block content}
diff --git a/ipf/admin/templates/admin/delete.html b/ipf/admin/templates/admin/delete.html index 15ade53..0026790 100644 --- a/ipf/admin/templates/admin/delete.html +++ b/ipf/admin/templates/admin/delete.html @@ -1,24 +1,23 @@ {extends "admin/base.html"} -{block breadcrumbs}{/block} +{block breadcrumbs} + +{/block} {block content}
-

{$page_title}

-
- -

Are you sure you want to delete {$object}? -

- {if count($affected) > 0} -

It will also delete the following linked elements:

-
    - {foreach $affected as $aff}
  • {$aff}
  • {/foreach} -
- {/if} +

{$page_title}

+ + +

Are you sure you want to delete {$object}?

-
+
- {/block} diff --git a/ipf/admin/templates/admin/index.html b/ipf/admin/templates/admin/index.html index da366e4..9236fe3 100644 --- a/ipf/admin/templates/admin/index.html +++ b/ipf/admin/templates/admin/index.html @@ -11,11 +11,11 @@ - {foreach $app.models as $model} + {foreach $app.components as $component} - - - + + + {/foreach} {foreach $app.additions as $item} diff --git a/ipf/admin/templates/admin/items.html b/ipf/admin/templates/admin/items.html index e6d8e6a..26dbd32 100644 --- a/ipf/admin/templates/admin/items.html +++ b/ipf/admin/templates/admin/items.html @@ -15,7 +15,7 @@
@@ -35,7 +35,7 @@ {if $search_value} - {$pager->getPager()->getNumResults()} results (reset) + {$count} results (reset) {/if}
@@ -62,14 +62,14 @@ {foreach $header as $h} - + {/foreach} - {foreach $objects as $o} - - {foreach $o.ModelAdmin().ListRow($o) as $v} + {foreach $objects as $id => $o} + + {foreach $component->ListRow($o, $id) as $v} {/foreach} @@ -78,7 +78,18 @@
{$app.name|escxml}
{$model.name}{if array_search('add',$model['perms'])!==false}{trans 'Add'}{/if}{if array_search('change',$model['perms'])!==false}{trans 'Change'}{/if}{$component->verbose_name()}{if $component->isAccessible(array('add'))}{trans 'Add'}{/if}{trans 'Change'}
{$h.title}{$h['title']}
{$v|safe}
{/block}

- {$pager->display()|safe}{$pager->getPager()->getNumResults()} record(s) of {$classname} + {foreach $pages as $p} + {if $p} + {if $p == $current_page} + {$p} + {else} + {$p} + {/if} + {else} + … + {/if} + {/foreach} + {$count} record(s) of {$classname}

diff --git a/ipf/admin/views.php b/ipf/admin/views.php index 43d2be0..8a42707 100644 --- a/ipf/admin/views.php +++ b/ipf/admin/views.php @@ -2,43 +2,26 @@ function IPF_Admin_Views_Index($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; + IPF_Admin_App::ensureUserIsStaff($request); $apps = array(); $app_list = new IPF_Template_ContextVars(); foreach (IPF_Project::getInstance()->appList() as $app) { - $appModels = IPF_Legacy_ORM_App::appModelList($app); - if (!$appModels) - continue; - - $models = new IPF_Template_ContextVars(); - $models_found = false; - foreach ($appModels as $m) { - $ma = IPF_Admin_Model::getModelAdmin($m); - if ($ma!==null && !$ma->hidden){ - $perms = $ma->getPerms($request); - if (array_search('view', $perms)!==false){ - $user_perms = IPF_Auth_App::checkPermissions($request, $app, $m, array('view')); - if ($user_perms['view']) - { - $models[] = new IPF_Template_ContextVars(array( - 'name'=>$ma->verbose_name(), - 'path'=>strtolower($m), - 'perms'=>$perms, - )); - $models_found = true; - } - } + $components = array(); + foreach (IPF_Admin_App::applicationComponents($app) as $component) { + if ($component->isAccessible(array('view'), $request)) { + $component->request = $request; + $components[] = $component; } } - if ($models_found){ - $app_list[$app->getName()] = new IPF_Template_ContextVars(array( + + if ($components) { + $app_list[] = (object)array( 'name' => $app->getTitle(), - 'path' => $app->getSlug(), + 'path' => $app->slug(), 'additions' => $app->getAdditions(), - 'models' => $models, - )); + 'components' => $components, + ); } } @@ -59,215 +42,69 @@ function IPF_Admin_Views_Index($request, $match) function IPF_Admin_Views_ListItems($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; - - $lapp = $match[1]; - $lmodel = $match[2]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) - { - $app = $am['app']; - $m = $am['modelname']; - - $ma = IPF_Admin_Model::getModelAdmin($m); - - if ($ma !== null) - return $ma->ListItems($request, $lapp, $lmodel); - } - - return new IPF_HTTP_Response_NotFound($request); + $component = IPF_Admin_App::getComponent($request, array('view')); + return $component->ListItems($request); } function IPF_Admin_Views_AddItem($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; - - $lapp = $match[1]; - $lmodel = $match[2]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) - { - $app = $am['app']; - $m = $am['modelname']; - - $ma = IPF_Admin_Model::getModelAdmin($m); - - if ($ma !== null) - return $ma->AddItem($request, $lapp, $lmodel); - } - - return new IPF_HTTP_Response_NotFound($request); + $component = IPF_Admin_App::getComponent($request, array('view', 'add')); + return $component->AddItem($request); } function IPF_Admin_Views_EditItem($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; - - $lapp = $match[1]; - $lmodel = $match[2]; - $id = $match[3]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) { - $m = $am['modelname']; - $ma = IPF_Admin_Model::getModelAdmin($m); - if ($ma !== null) { - $item = IPF_ORM::getTable($m)->find($id); - if (!$item) - throw new IPF_HTTP_Error404(); - return $ma->EditItem($request, $lapp, $lmodel, $item); - } - } - - return new IPF_HTTP_Response_NotFound($request); + $component = IPF_Admin_App::getComponent($request, array('view', 'change')); + return $component->EditItem($request, $request->params[3]); } function IPF_Admin_Views_DeleteItem($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; - - $lapp = $match[1]; - $lmodel = $match[2]; - $id = $match[3]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) - { - $app = $am['app']; - $m = $am['modelname']; - - $ma = IPF_Admin_Model::getModelAdmin($m); - - if ($ma !== null) - { - $o = new $m(); - $item = $o->getTable()->find($id); - if (!$item) - throw new IPF_HTTP_Error404(); - - return $ma->DeleteItem($request, $lapp, $lmodel, $item); - } - } - - return new IPF_HTTP_Response_NotFound($request); + $component = IPF_Admin_App::getComponent($request, array('view', 'delete')); + return $component->DeleteItem($request, $request->params[3]); } function IPF_Admin_Views_Reorder($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; + $component = IPF_Admin_App::getComponent($request, array('view', 'change')); if ($request->method != 'POST' || !isset($request->POST['ids']) || !is_array($request->POST['ids'])) return new IPF_HTTP_Response_NotFound($request); - $lapp = $match[1]; - $lmodel = $match[2]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) { - $app = $am['app']; - $m = $am['modelname']; - - $user_perms = IPF_Auth_App::checkPermissions($request, $app, $m, array('view', 'change')); - $ma = ($user_perms['view'] && $user_perms['change']) ? IPF_Admin_Model::getModelAdmin($m) : null; - - if ($ma !==null && $ma->_orderable()) { - $ord_field = $ma->_orderableColumn(); - - $ids = $request->POST['ids']; - - $table = IPF_ORM::getTable($m); - $conn = $table->getConnection(); - - $idColumn = $table->getIdentifier(); - if (is_array($idColumn)) - $idColumn = $idColumn[0]; - - $questions = str_repeat('?,', count($ids)-1) . '?'; - $query = 'SELECT ' . $conn->quoteIdentifier($ord_field) . - ' FROM ' . $conn->quoteIdentifier($table->getTableName()) . - ' WHERE ' . $conn->quoteIdentifier($idColumn) . ' IN (' . $questions . ')' . - ' ORDER BY ' . $conn->quoteIdentifier($ord_field); - $ords = $conn->fetchColumn($query, $ids); - - $i = 0; - foreach ($ids as $id) { - $item = $table->find($id); - $item[$ord_field] = $ords[$i]; - $item->save(); - $i++; - } - - return new IPF_HTTP_Response_Json("Ok"); - } - } - - return new IPF_HTTP_Response_Json("Cannot find model"); + if ($component->reorder($request->POST['ids'])) + return new IPF_HTTP_Response_Json("Ok"); + else + return new IPF_HTTP_Response_Json('Cannot find model'); } function IPF_Admin_Views_ChangePassword($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; + $component = IPF_Admin_App::getComponent($request, array('view', 'change')); - $lapp = 'auth'; - $lmodel = 'user'; - $id = $match[1]; - - $am = IPF_Admin_App::GetAppModelFromSlugs($lapp, $lmodel); - - if ($am !== null) - { - $app = $am['app']; - $m = $am['modelname']; - - $ma = IPF_Admin_Model::getModelAdmin($m); - - if ($ma !== null) - { - $o = new $m(); - $user = $o->getTable()->find($id); - - if ($request->method == 'POST') - { - $form = new IPF_Auth_Forms_ChangePassword($request->POST); - - if ($form->isValid()) - { - $user->setPassword($form->cleaned_data['password1']); - $user->save(); - - return new IPF_HTTP_Response_Redirect(IPF_HTTP_URL::urlForView('IPF_Admin_Views_ListItems', array($lapp, $lmodel))); - } - } - else $form = new IPF_Auth_Forms_ChangePassword(); - - $context = array( - 'page_title'=>'Change Password: '.$user->username, - 'classname'=>'User', - 'object'=>$user, - 'form' => $form, - 'extra_js' => array(), - 'lapp'=>$lapp, - 'lmodel'=>$lmodel, - ); - - return IPF_Admin_App::RenderToResponse('admin/changepassword.html', $context, $request); + $user = User::table()->find($match[1]); + + if ($request->method == 'POST') { + $form = new IPF_Admin_Forms_ChangePassword($request->POST); + if ($form->isValid()) { + $user->setPassword($form->cleaned_data['password1']); + $user->save(); + return new IPF_HTTP_Response_Redirect('../'); } + } else { + $form = new IPF_Admin_Forms_ChangePassword(); } - - return new IPF_HTTP_Response_NotFound($request); + + $context = array( + 'component' => $this, + 'app' => $app, + 'page_title'=>'Change Password: '.$user->username, + 'classname'=>'User', + 'object'=>$user, + 'form' => $form, + 'extra_js' => array(), + ); + + return IPF_Admin_App::RenderToResponse('admin/changepassword.html', $context, $request); } function IPF_Admin_Views_Login($request, $match) @@ -279,13 +116,13 @@ function IPF_Admin_Views_Login($request, $match) $success_url = IPF_HTTP_URL::urlForView('IPF_Admin_Views_Index'); if ($request->method == 'POST') { - $form = new IPF_Auth_Forms_Login($request->POST); + $form = new IPF_Admin_Forms_Login($request->POST); if ($form->isValid()) { IPF_Auth_App::login($request, $form->user); return new IPF_HTTP_Response_Redirect($success_url); } } else { - $form = new IPF_Auth_Forms_Login(array('next'=>$success_url)); + $form = new IPF_Admin_Forms_Login(array('next'=>$success_url)); } $context = array( @@ -355,8 +192,7 @@ function dir_recursive($dir, $path=DIRECTORY_SEPARATOR, $level='') function IPF_Admin_Views_FileBrowser($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; + IPF_Admin_App::ensureUserIsStaff($request); $curr_dir = urldecode(substr($match[1],1)); if (substr($curr_dir, -1) == '/') @@ -459,8 +295,7 @@ function IPF_Admin_Views_FileBrowser($request, $match) function IPF_Admin_Views_FileBrowserRename($request, $match) { - $ca = IPF_Admin_App::checkAdminAuth($request); - if ($ca!==true) return $ca; + IPF_Admin_App::ensureUserIsStaff($request); $old_name = @$request->POST['old_value']; $name = @$request->POST['value']; diff --git a/ipf/application.php b/ipf/application.php index 458a370..fc138f4 100644 --- a/ipf/application.php +++ b/ipf/application.php @@ -37,7 +37,7 @@ abstract class IPF_Application return $this->path; } - public function getSlug() + public function slug() { $e = explode('_',$this->name); return strtolower($e[count($e)-1]); diff --git a/ipf/auth/admin.php b/ipf/auth/admin.php new file mode 100644 index 0000000..d03d914 --- /dev/null +++ b/ipf/auth/admin.php @@ -0,0 +1,379 @@ +isAdd = $extra['is_add']; + + $this->fields['username'] = new IPF_Form_Field_Varchar(array( + 'required' => true, + 'max_length' => 32, + 'label' => __('Username'), + 'help_text' => __('Required. 32 characters or less. Alphanumeric characters only (letters, digits and underscores).'), + )); + $this->fields['password'] = new IPF_Form_Field_Varchar(array( + 'required' => true, + 'max_length' => 128, + 'label' => __('Password'), + )); + + $this->fields['email'] = new IPF_Form_Field_Email(array( + 'required' => true, + 'max_length' => 200, + 'label' => __('E-mail'), + )); + + $this->fields['is_active'] = new IPF_Form_Field_Boolean(array( + 'label' => __('Active'), + 'help_text' => __('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'), + )); + $this->fields['is_staff'] = new IPF_Form_Field_Boolean(array( + 'label' => __('Staff status'), + 'help_text' => __('Designates whether the user can log into this admin site.'), + )); + $this->fields['is_superuser'] = new IPF_Form_Field_Boolean(array( + 'label' => __('Superuser status'), + 'help_text' => __('Designates that this user has all permissions without explicitly assigning them.'), + )); + + if ($this->isAdd) { + unset($this->fields['password']); + + $this->fields['password1'] = new IPF_Form_Field_Varchar(array( + 'label' => __('Password'), + 'required' => true, + 'max_length' => 32, + 'widget' => 'IPF_Form_Widget_PasswordInput' + )); + + $this->fields['password2'] = new IPF_Form_Field_Varchar(array( + 'label' => __('Password (again)'), + 'required' => true, + 'max_length' => 32, + 'widget' => 'IPF_Form_Widget_PasswordInput', + 'help_text' => __('Enter the same password as above, for verification.'), + )); + + $account = array('username', 'password1', 'password2', 'email'); + } else { + $this->fields['password']->help_text = __("Use '[algo]$[salt]$[hexdigest]' or use the change password form."); + + $account = array('username', 'password', 'email'); + } + + $permissions = array('is_active', 'is_staff', 'is_superuser'); + if (IPF_Auth_App::ArePermissionsEnabled()) { + $permissions[] = 'permissions'; + $permissions[] = 'roles'; + + $this->fields['permissions'] = new IPF_Form_Field_MultipleChoice(array( + 'label' => __('Permissions'), + 'choices' => Permission::query()->fetchPairs('title', 'id'), + 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', + 'widget_attrs' => array('class' => 'checkgroup'), + )); + + $this->fields['roles'] = new IPF_Form_Field_MultipleChoice(array( + 'label' => __('Groups'), + 'help_text' => __('In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.'), + 'choices' => Role::query()->fetchPairs('name', 'id'), + 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', + 'widget_attrs' => array('class' => 'checkgroup'), + )); + } + + $this->field_groups = array( + array('fields' => $account), + array('fields' => $permissions, 'label' => __('Permissions')), + ); + } + + function isValid() + { + $ok = parent::isValid(); + + if ($ok===true && $this->isAdd) { + if ($this->cleaned_data['password1'] != $this->cleaned_data['password2']) { + $this->is_valid = false; + $this->errors['password2'][] = "The two password fields didn't match."; + + return false; + } + + $this->cleaned_data['password'] = User::SetPassword2($this->cleaned_data['password1']); + } + + return $ok; + } +} + +class AdminUser extends IPF_Admin_Component +{ + public function ListItemsQuery($searchValue, $page, $pageSize) + { + return User::query() + ->limit($pageSize) + ->offset(($page - 1) * $pageSize) + ->fetchAll('id'); + } + + public function ListItemsQueryCount($searchValue) + { + return User::query() + ->select(null)->select('COUNT(1)') + ->fetchColumn(); + } + + public function list_display() + { + $columns = array( + 'username', + 'email', + 'is_active', + 'is_staff', + 'is_superuser', + ); + if (IPF_Auth_App::ArePermissionsEnabled()) { + $columns[] = 'groups'; + } + return $columns; + } + + public function column_groups($obj) + { + return \PFF\Arr::create($obj->roles())->pluck('name')->join(' / '); + } + + function _searchFields() + { + return array( + 'username', + 'email', + ); + } + + public function renderCell($object, $column) + { + return $object->$column; + } + + public function getObjectByID($id) + { + return User::query()->where('id', $id)->fetch(); + } + + protected function _getForm($user, $data) + { + $extra = array(); + if ($user) { + $extra['initial'] = array( + 'username' => $user->username, + 'password' => $user->password, + 'email' => $user->email, + 'is_active' => $user->is_active, + 'is_staff' => $user->is_staff, + 'is_superuser' => $user->is_superuser, + 'permissions' => \PFF\Arr::create($user->permissions())->pluck('id')->arr(), + 'roles' => \PFF\Arr::create($user->roles())->pluck('id')->arr(), + ); + $extra['is_add'] = false; + } else { + $extra['is_add'] = true; + } + return new IPFAuthAdminUserForm($data, $extra); + } + + public function saveObject($form, $user) + { + if (!$user) + $user = new User; + + if ($user->id) { + } else { + } + +/* + + \PFF\Container::databaseQuery() + ->deleteFrom('auth_user_permission') + ->where('user_id', $user->id) + ->execute(); + + $query = \PFF\Container::databaseQuery() + ->insertInto('auth_user_permission'); + foreach ($this->cleaned_data['permissions'] as $pid) + $query->values(array('user_id' => $user->id, 'permission_id' => $pid)); + $query->execute(); + + + \PFF\Container::databaseQuery() + ->deleteFrom('auth_user_group') + ->where('user_id', $user->id) + ->execute(); + + $query = \PFF\Container::databaseQuery() + ->insertInto('auth_user_role'); + foreach ($this->cleaned_data['roles'] as $pid) + $query->values(array('user_id' => $user->id, 'role_id' => $pid)); + $query->execute(); + + + */ + return array($user->id, $user); + } + + public function deleteObject($user) + { + \PFF\Container::databaseQuery() + ->deleteFrom('auth_user') + ->where('id', $user->id) + ->execute(); + } + + protected function objectTools($user) + { + return array( + 'impersonate' => IPF_HTTP_URL::urlForView('IPF_Admin_Views_Impersonate', array($user->id)), + ); + } + + public function verbose_name() { return 'User'; } +} + +class IPFAdminRoleForm extends IPF_Form +{ + function initFields($extra=array()) + { + $this->fields['name'] = new IPF_Form_Field_Varchar(array( + 'required' => true, + 'label' => __('Name'), + 'max_length' => 255, + )); + + if (IPF_Auth_App::ArePermissionsEnabled()) { + $this->fields['permissions'] = new IPF_Form_Field_MultipleChoice(array( + 'label' => __('Permissions'), + 'choices' => Permission::query()->fetchPairs('title', 'id'), + 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', + 'widget_attrs' => array('class' => 'checkgroup'), + )); + } + } +} + +class AdminRole extends IPF_Admin_Component +{ + public function ListItemsQuery($searchValue, $page, $pageSize) + { + return Role::query() + ->limit($pageSize) + ->offset(($page - 1) * $pageSize) + ->fetchAll('id'); + } + + public function ListItemsQueryCount($searchValue) + { + return Role::query() + ->select(null)->select('COUNT(1)') + ->fetchColumn(); + } + + public function list_display() + { + return array( + 'name', + ); + } + + public function renderCell($object, $column) + { + return $object->$column; + } + + function _searchFields() + { + return array( + 'name', + ); + } + + public function getObjectByID($id) + { + return Role::query()->where('id', $id)->fetch(); + } + + protected function _getForm($role, $data) + { + $extra = array(); + if ($role) { + $extra['initial'] = array( + 'name' => $role->name, + 'permissions' => \PFF\Arr::create($role->permissions())->pluck('id')->arr(), + ); + } + return new IPFAdminRoleForm($data, $extra); + } + + public function saveObject($form, $role) + { + if (!$role) + $role = new Role; + + $role->name = $form->cleaned_data['name']; + if ($role->id) { + \PFF\Container::databaseQuery() + ->update('auth_role') + ->set('name', $role->name) + ->where('id', $role->id) + ->execute(); + + \PFF\Container::databaseQuery() + ->deleteFrom('auth_role_permission') + ->where('role_id', $role->id) + ->execute(); + } else { + $role->id = \PFF\Container::databaseQuery() + ->insertInto('auth_role') + ->values(array('name' => $role->name)) + ->execute(); + } + + if ($form->cleaned_data['permissions']) { + $data = array_map(function($pid) use($role) { return array('role_id' => $role->id, 'permission_id' => $pid); }, + $form->cleaned_data['permissions']); + + \PFF\Container::databaseQuery() + ->insertInto('auth_role_permission') + ->values($data) + ->execute(); + } + + return array($role->id, $role); + } + + public function deleteObject($role) + { + \PFF\Container::databaseQuery() + ->deleteFrom('auth_role') + ->where('id', $role->id) + ->execute(); + } + + public function page_title() { return 'Group'; } + public function verbose_name() { return 'Group'; } +} + +if (IPF_Auth_App::ArePermissionsEnabled()) { + return array( + 'AdminUser', + 'AdminRole', + ); +} else { + return array( + 'AdminUser', + ); +} + diff --git a/ipf/auth/app.php b/ipf/auth/app.php index 81affdd..f7134df 100644 --- a/ipf/auth/app.php +++ b/ipf/auth/app.php @@ -2,9 +2,9 @@ class IPF_Auth_App extends IPF_Application { - public function admin_models_order() + public function getTitle() { - return array('User', 'Role'); + return 'User Accounts'; } static function login($request, $user) @@ -13,12 +13,6 @@ class IPF_Auth_App extends IPF_Application $request->session->data = array( 'login_time' => gmdate('Y-m-d H:i:s') ); - $user->save(); - } - - public function getTitle() - { - return 'User Accounts'; } static function logout($request) @@ -29,64 +23,16 @@ class IPF_Auth_App extends IPF_Application ); } - static function ArePermissionsEnabled() - { - try { - return IPF_ORM_Query::create()->from('Permission')->count() ? true : false; - } catch (IPF_ORM_Exception $e) { - return true; - } - } + private static $permissionsEnabled = null; - static function checkPermissions($request, $app, $modelName, array $perms) + static function ArePermissionsEnabled() { - $count = count($perms); - - if (!$count) - return array(); - - $permissions = array_combine($perms, array_fill(0, $count, false)); - - if ($request->user->isAnonymous() || !($request->user->is_staff || $request->user->is_superuser)) - return $permissions; - - if ($request->user->is_superuser || !self::ArePermissionsEnabled()) - return array_combine($perms, array_fill(0, $count, true)); - - $user_permissions = array(); - - foreach ($request->user->Permissions as $up) - $user_permissions[] = $up->name; - - foreach ($request->user->Roles as $role) - { - foreach ($role->Permissions as $rp) - { - if (!in_array($rp->name, $user_permissions)) - $user_permissions[] = $rp->name; - } - } - - if (!count($user_permissions)) - return $permissions; - - $prefix = get_class($app).'|'.$modelName.'|'; - - foreach ($permissions as $permName=>&$permValue) - { - $permissionValue = $prefix.$permName; - - foreach ($user_permissions as $user_permission_value) - { - if ($permissionValue == $user_permission_value) - { - $permValue = true; - break; - } - } - } - - return $permissions; + if (self::$permissionsEnabled === null) + self::$permissionsEnabled = (bool)\PFF\Container::databaseQuery() + ->from('auth_permission') + ->select('COUNT(1)') + ->fetchColumn(); + return self::$permissionsEnabled; } public function commands() diff --git a/ipf/auth/middleware.php b/ipf/auth/middleware.php index 455403c..0cf563a 100644 --- a/ipf/auth/middleware.php +++ b/ipf/auth/middleware.php @@ -10,7 +10,7 @@ class IPF_Auth_Middleware $user_id = \PFF\Arr::get($request->session->data, self::SessionKey, 0); if ($user_id > 0) { - $request->user = User::table()->find($user_id); + $request->user = User::find($user_id); if ($request->user && 43200 < IPF_Utils::dateCompare($request->user->last_login)) { $request->user->last_login = gmdate('Y-m-d H:i:s'); $request->user->save(); diff --git a/ipf/auth/migrations/20140102000000_create_auth_tables.php b/ipf/auth/migrations/20140102000000_create_auth_tables.php new file mode 100644 index 0000000..e3e953a --- /dev/null +++ b/ipf/auth/migrations/20140102000000_create_auth_tables.php @@ -0,0 +1,23 @@ +connection->exec('CREATE TABLE auth_user (id BIGINT AUTO_INCREMENT, username VARCHAR(32) NOT NULL UNIQUE, password VARCHAR(128) NOT NULL, email VARCHAR(200) NOT NULL UNIQUE, is_staff TINYINT(1) NOT NULL DEFAULT 0, is_active TINYINT(1) NOT NULL DEFAULT 0, is_superuser TINYINT(1) NOT NULL DEFAULT 0, last_login TIMESTAMP, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB'); + $this->connection->exec('CREATE TABLE auth_role (id BIGINT AUTO_INCREMENT, name VARCHAR(255) UNIQUE, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB'); + $this->connection->exec('CREATE TABLE auth_permission (id BIGINT AUTO_INCREMENT, name VARCHAR(255) NOT NULL UNIQUE, title VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB'); + + $this->connection->exec('CREATE TABLE auth_user_permission (user_id BIGINT, permission_id BIGINT, PRIMARY KEY(user_id, permission_id)) ENGINE = INNODB'); + $this->connection->exec('CREATE TABLE auth_user_role (user_id BIGINT, role_id BIGINT, PRIMARY KEY(user_id, role_id)) ENGINE = INNODB'); + $this->connection->exec('CREATE TABLE auth_role_permission (role_id BIGINT, permission_id BIGINT, PRIMARY KEY(role_id, permission_id)) ENGINE = INNODB'); + + $this->connection->exec('ALTER TABLE auth_user_permission ADD FOREIGN KEY (user_id) REFERENCES auth_user(id) ON DELETE CASCADE'); + $this->connection->exec('ALTER TABLE auth_user_permission ADD FOREIGN KEY (permission_id) REFERENCES auth_permission(id) ON DELETE CASCADE'); + $this->connection->exec('ALTER TABLE auth_user_role ADD FOREIGN KEY (user_id) REFERENCES auth_user(id) ON DELETE CASCADE'); + $this->connection->exec('ALTER TABLE auth_user_role ADD FOREIGN KEY (role_id) REFERENCES auth_role(id) ON DELETE CASCADE'); + $this->connection->exec('ALTER TABLE auth_role_permission ADD FOREIGN KEY (role_id) REFERENCES auth_role(id) ON DELETE CASCADE'); + $this->connection->exec('ALTER TABLE auth_role_permission ADD FOREIGN KEY (permission_id) REFERENCES auth_permission(id) ON DELETE CASCADE'); + } +} + diff --git a/ipf/auth/models.php b/ipf/auth/models.php index 5012883..933cdcb 100644 --- a/ipf/auth/models.php +++ b/ipf/auth/models.php @@ -1,5 +1,134 @@ username; + if ($s===null) + return 'Anonymous'; + return $s; + } + + function setPassword($raw_password) + { + if ($raw_password) + $this->password = IPF_Crypto::hashPassword($raw_password); + else + $this->password = ''; + } + + function isAnonymous() + { + return 0 === (int)$this->id; + } + + public static function find($id) + { + return self::query()->where('id', $id)->fetch(); + } + + public static function checkCreditentials($username, $password) + { + $user = self::query()->where('username', $username)->fetch(); + if ($user && $user->is_active && IPF_Crypto::checkPassword($password, $user->password)) + return $user; + else + return false; + } + + public static function query() + { + return \PFF\Container::databaseQuery() + ->from('auth_user') + ->orderBy('username') + ->asObject('User'); + } + + public function permissions() + { + return Permission::query() + ->innerJoin('auth_user_permission ON permission_id = id') + ->where('user_id', $this->id) + ->fetchAll(); + } + + public function roles() + { + return Role::query() + ->innerJoin('auth_user_role ON role_id = id') + ->where('user_id', $this->id) + ->fetchAll(); + } + + public function effectivePermissions() + { + return Permission::query() + ->where( + 'EXISTS(SELECT 1 FROM auth_user_permission AS up ' . + ' WHERE up.permission_id = auth_permission.id' . + ' AND up.user_id = :user_id)' . + ' OR '. + 'EXISTS(SELECT 1 FROM auth_user_role AS ur, auth_role_permission AS rp'. + ' WHERE rp.permission_id = auth_permission.id'. + ' AND rp.role_id = ur.role_id' . + ' AND ur.user_id = :user_id)', array('user_id' => $this->id)); + } + + public function can(/* $permission ... */) + { + $cond = array(); + $params = array(); + foreach (func_get_args() as $permission) { + if ($permission instanceof Permission) { + $cond[] = 'id = ?'; + $params[] = $permission->id; + } elseif (is_int($permission)) { + $cond[] = 'id = ?'; + $params[] = $permission; + } elseif (is_string($permission)) { + $cond[] = 'name = ?'; + $params[] = $permission; + } else { + throw new IPF_Exception('Bad argument'); + } + } + + return $this->effectivePermissions() + ->select(null)->select('COUNT(1)') + ->where(implode(' OR ', $cond), $params) + ->fetchColumn() == count($params); + } +} + +class Role +{ + public $id, $name; + + public function __toString() + { + return $this->name; + } + + public static function query() + { + return \PFF\Container::databaseQuery() + ->from('auth_role') + ->asObject('Role') + ->orderBy('name'); + } + + public function permissions() + { + return Permission::query() + ->innerJoin('auth_role_permission ON permission_id = id') + ->where('role_id', $this->id) + ->fetchAll(); + } +} + class Permission { public $id, $name, $title; diff --git a/ipf/auth/models.yml b/ipf/auth/models.yml deleted file mode 100644 index 1d1515c..0000000 --- a/ipf/auth/models.yml +++ /dev/null @@ -1,146 +0,0 @@ ---- -User: - tableName: auth_user - actAs: [Timestampable] - columns: - username: - type: string(32) - notblank: true - notnull: true - unique: true - password: - type: string(128) - notblank: true - notnull: true - first_name: string(32) - last_name: string(32) - email: - type: string(200) - email: true - notnull: true - notblank: true - unique: true - is_staff: - type: boolean - notnull: true - default: false - is_active: - type: boolean - notnull: true - default: false - is_superuser: - type: boolean - notnull: true - default: false - last_login: - type: timestamp - relations: - Roles: - class: Role - refClass: UserRole - foreignAlias: Users - Permissions: - class: Permission - refClass: UserPermission - foreignAlias: Users - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- -Role: - tableName: auth_role - columns: - name: - unique: true - type: string(255) - notblank: true - relations: - Permissions: - class: Permission - refClass: RolePermission - foreignAlias: Roles - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- -Permission: - tableName: auth_permission - columns: - name: - unique: true - type: string(255) - notnull: true - title: - type: string(255) - notnull: true - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- -RolePermission: - tableName: auth_role_permission - columns: - role_id: - type: integer - primary: true - permission_id: - type: integer - primary: true - relations: - Role: - local: role_id - onDelete: CASCADE - Permission: - local: permission_id - onDelete: CASCADE - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- -UserRole: - tableName: auth_user_role - columns: - user_id: - type: integer - primary: true - role_id: - type: integer - primary: true - relations: - User: - local: user_id - onDelete: CASCADE - Role: - local: role_id - onDelete: CASCADE - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- -UserPermission: - tableName: auth_user_permission - columns: - user_id: - type: integer - primary: true - permission_id: - type: integer - primary: true - relations: - User: - local: user_id - onDelete: CASCADE - Permission: - local: permission_id - onDelete: CASCADE - options: - type: INNODB - collate: utf8_unicode_ci - charset: utf8 ---- - diff --git a/ipf/auth/models/Permission.php b/ipf/auth/models/Permission.php deleted file mode 100644 index 30943f2..0000000 --- a/ipf/auth/models/Permission.php +++ /dev/null @@ -1,10 +0,0 @@ -title; - } -} - diff --git a/ipf/auth/models/Role.php b/ipf/auth/models/Role.php deleted file mode 100644 index 4281783..0000000 --- a/ipf/auth/models/Role.php +++ /dev/null @@ -1,73 +0,0 @@ -name; - } -} - -class IPFAdminRoleForm extends IFP_Admin_ModelForm -{ - public function add__Permissions__field() - { - if (!IPF_Auth_App::ArePermissionsEnabled()) - return null; - - $choices = array(); - foreach (IPF_ORM::getTable('Permission')->findAll() as $o) - $choices[$o->__toString()] = $o->id; - ksort($choices); - - return new IPF_Form_Field_ModelMultipleChoice(array( - 'required' => false, - 'label' => 'Permissions', - 'help_text' => '', - 'type' => 'manytomany', - 'editable' => true, - 'model' => 'Permission', - 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', - 'choices' => $choices, - 'widget_attrs' => array('class' => 'checkgroup'), - )); - } -} - -class AdminRole extends IPF_Admin_Model -{ - public function list_display() - { - return array( - 'name', - ); - } - - public function fields() - { - return array( - 'name', - 'Permissions', - ); - } - - function _searchFields() - { - return array( - 'name', - ); - } - - protected function _getForm($model_obj, $data, $extra) - { - $extra['model'] = $model_obj; - return new IPFAdminRoleForm($data, $extra); - } - - public function page_title() { return 'Group'; } - public function verbose_name() { return 'Group'; } -} - -if (IPF_Auth_App::ArePermissionsEnabled()) - IPF_Admin_Model::register('Role', 'AdminRole'); - diff --git a/ipf/auth/models/RolePermission.php b/ipf/auth/models/RolePermission.php deleted file mode 100644 index c407a8c..0000000 --- a/ipf/auth/models/RolePermission.php +++ /dev/null @@ -1,6 +0,0 @@ -fields['email']->label = 'E-mail'; - - $this->fields['is_active']->label = __('Active'); - $this->fields['is_staff']->label = __('Staff status'); - $this->fields['is_superuser']->label = __('Superuser status'); - - $this->fields['is_active']->help_text = __('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'); - $this->fields['is_staff']->help_text = __('Designates whether the user can log into this admin site.'); - $this->fields['is_superuser']->help_text = __('Designates that this user has all permissions without explicitly assigning them.'); - - $this->fields['username']->help_text = __('Required. 32 characters or less. Alphanumeric characters only (letters, digits and underscores).'); - - if (!$this->model->id) { - unset($this->fields['password']); - - $this->fields['password1'] = new IPF_Form_Field_Varchar(array( - 'label' => __('Password'), - 'required' => true, - 'max_length' => 32, - 'widget' => 'IPF_Form_Widget_PasswordInput' - )); - - $this->fields['password2'] = new IPF_Form_Field_Varchar(array( - 'label' => __('Password (again)'), - 'required' => true, - 'max_length' => 32, - 'widget' => 'IPF_Form_Widget_PasswordInput', - 'help_text' => __('Enter the same password as above, for verification.'), - )); - - $account = array('username', 'password1', 'password2'); - } else { - $this->fields['password']->help_text = __("Use '[algo]$[salt]$[hexdigest]' or use the change password form."); - - $account = array('username', 'password'); - } - - $permissions = array('is_active', 'is_staff', 'is_superuser'); - if (IPF_Auth_App::ArePermissionsEnabled()) { - $permissions[] = 'Permissions'; - $permissions[] = 'Roles'; - } - - $this->field_groups = array( - array('fields' => $account), - array('fields' => array('email', 'first_name', 'last_name'), 'label' => __('Personal info')), - array('fields' => $permissions, 'label' => __('Permissions')), - ); - - /* - * User's profile - */ - - $profileTable = IPF::get('auth_profile_model'); - if ($profileTable) { - $table = IPF_ORM::getTable($profileTable); - $profileFields = self::suggestFields($table); - - $fieldGroup = array(); - foreach ($profileFields as $field) { - list($n, $f) = $field; - $this->fields[$n] = $f; - $fieldGroup[] = $n; - } - - $this->field_groups[] = array('fields' => $fieldGroup, 'label' => __('Profile')); - } - } - - public function add__Permissions__field() - { - if (!IPF_Auth_App::ArePermissionsEnabled()) - return null; - - $choices = array(); - foreach (IPF_ORM::getTable('Permission')->findAll() as $o) - $choices[$o->__toString()] = $o->id; - ksort($choices); - - return new IPF_Form_Field_ModelMultipleChoice(array( - 'required' => false, - 'label' => 'Permissions', - 'help_text' => '', - 'type' => 'manytomany', - 'editable' => true, - 'model' => 'Permission', - 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', - 'choices' => $choices, - 'widget_attrs' => array('class' => 'checkgroup'), - )); - } - - public function add__Roles__field() - { - if (!IPF_Auth_App::ArePermissionsEnabled()) - return null; - - $choices = array(); - foreach (IPF_ORM::getTable('Role')->findAll() as $o) - $choices[$o->__toString()] = $o->id; - - return new IPF_Form_Field_ModelMultipleChoice(array( - 'required' => false, - 'label' => 'Groups', - 'help_text' => 'In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.', - 'type' => 'manytomany', - 'editable' => true, - 'model' => 'Role', - 'widget' => 'IPF_Form_Widget_SelectMultipleInputCheckbox', - 'choices' => $choices, - 'widget_attrs' => array('class' => 'checkgroup'), - )); - } - - function isValid() - { - $ok = parent::isValid(); - - if ($ok===true && !$this->model->id) { - if ($this->cleaned_data['password1'] != $this->cleaned_data['password2']) { - $this->is_valid = false; - $this->errors['password2'][] = "The two password fields didn't match."; - - return false; - } - - $this->cleaned_data['password'] = User::SetPassword2($this->cleaned_data['password1']); - } - - return $ok; - } - - function save($commit=true) - { - $user = parent::save($commit); - $profileTable = IPF::get('auth_profile_model'); - if ($profileTable) { - $profile = $user->getProfile(); - - $profile->SetFromFormData($this->cleaned_data); - $profile->save(); - } - return $user; - } -} - -class AdminUser extends IPF_Admin_Model -{ - public function list_display() - { - $columns = array( - 'username', - 'email', - 'is_active', - 'is_staff', - 'is_superuser', - ); - if (IPF_Auth_App::ArePermissionsEnabled()) { - $columns[] = 'groups'; - } - $columns[] = 'created_at'; - return $columns; - } - - public function column_groups($obj) - { - $roles = array(); - foreach ($obj->Roles as $role) { - $roles[] = $role->name; - } - return implode(' / ', $roles); - } - - function _searchFields() - { - return array( - 'username', - 'email', - ); - } - - protected function _getForm($model_obj, $data, $extra) - { - $extra['model'] = $model_obj; - return new IPFAuthAdminUserForm($data, $extra); - } - - protected function objectTools($user) - { - return array( - 'impersonate' => IPF_HTTP_URL::urlForView('IPF_Admin_Views_Impersonate', array($user->id)), - ); - } -} - -class User extends BaseUser -{ - private $profile = null; - - public function __toString() - { - $s = $this->username; - if ($s===null) - return 'Anonymous'; - return $s; - } - - function setPassword($raw_password) - { - if ($raw_password) - $this->password = IPF_Crypto::hashPassword($raw_password); - else - $this->password = ''; - } - - function isAnonymous() - { - return 0 === (int)$this->id; - } - - public static function checkCreditentials($username, $password) - { - $user = self::table()->findOneByUsername($username); - if ($user && $user->is_active && IPF_Crypto::checkPassword($password, $user->password)) - return $user; - else - return false; - } - - public function getData() - { - $data = parent::getData(); - $profile = $this->getProfile(); - if ($profile) - $data = $data + $profile->getData(); - return $data; - } - - public function getProfile() - { - if (!$this->id) - return null; - - $profileTable = IPF::get('auth_profile_model'); - if (!$profileTable) - return null; - - if (!$this->profile) - $this->profile = IPF_ORM::getTable($profileTable)->findOneByUserId($this->id); - - if (!$this->profile) { - $this->profile = new $profileTable; - $this->profile->user = $this; - } - - return $this->profile; - } -} - -IPF_Admin_Model::register('User', 'AdminUser'); - diff --git a/ipf/auth/models/UserPermission.php b/ipf/auth/models/UserPermission.php deleted file mode 100644 index 7af37b9..0000000 --- a/ipf/auth/models/UserPermission.php +++ /dev/null @@ -1,6 +0,0 @@ -setTableName('auth_permission'); - $table->setColumn('name', 'string', 255, array('unique' => true, 'type' => 'string', 'notnull' => true, 'length' => '255')); - $table->setColumn('title', 'string', 255, array('type' => 'string', 'notnull' => true, 'length' => '255')); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasMany('User', 'Users', array('refClass' => 'UserPermission', 'local' => 'permission_id', 'foreign' => 'user_id')); - $table->hasMany('Role', 'Roles', array('refClass' => 'RolePermission', 'local' => 'permission_id', 'foreign' => 'role_id')); - $table->hasMany('RolePermission', '', array('local' => 'id', 'foreign' => 'permission_id')); - $table->hasMany('UserPermission', '', array('local' => 'id', 'foreign' => 'permission_id')); - } - - public static function table() - { - return IPF_ORM::getTable('Permission'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('Permission')->createQuery($alias); - } -} \ No newline at end of file diff --git a/ipf/auth/models/_generated/BaseRole.php b/ipf/auth/models/_generated/BaseRole.php deleted file mode 100644 index 0099fab..0000000 --- a/ipf/auth/models/_generated/BaseRole.php +++ /dev/null @@ -1,38 +0,0 @@ -setTableName('auth_role'); - $table->setColumn('name', 'string', 255, array('unique' => true, 'type' => 'string', 'notblank' => true, 'length' => '255')); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasMany('Permission', 'Permissions', array('refClass' => 'RolePermission', 'local' => 'role_id', 'foreign' => 'permission_id')); - $table->hasMany('User', 'Users', array('refClass' => 'UserRole', 'local' => 'role_id', 'foreign' => 'user_id')); - $table->hasMany('RolePermission', '', array('local' => 'id', 'foreign' => 'role_id')); - $table->hasMany('UserRole', '', array('local' => 'id', 'foreign' => 'role_id')); - } - - public static function table() - { - return IPF_ORM::getTable('Role'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('Role')->createQuery($alias); - } -} \ No newline at end of file diff --git a/ipf/auth/models/_generated/BaseRolePermission.php b/ipf/auth/models/_generated/BaseRolePermission.php deleted file mode 100644 index b4da1a4..0000000 --- a/ipf/auth/models/_generated/BaseRolePermission.php +++ /dev/null @@ -1,37 +0,0 @@ -setTableName('auth_role_permission'); - $table->setColumn('role_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setColumn('permission_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasOne('Role', '', array('local' => 'role_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - $table->hasOne('Permission', '', array('local' => 'permission_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - } - - public static function table() - { - return IPF_ORM::getTable('RolePermission'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('RolePermission')->createQuery($alias); - } -} \ No newline at end of file diff --git a/ipf/auth/models/_generated/BaseUser.php b/ipf/auth/models/_generated/BaseUser.php deleted file mode 100644 index 0411e71..0000000 --- a/ipf/auth/models/_generated/BaseUser.php +++ /dev/null @@ -1,47 +0,0 @@ -setTableName('auth_user'); - $table->setColumn('username', 'string', 32, array('type' => 'string', 'notblank' => true, 'notnull' => true, 'unique' => true, 'length' => '32')); - $table->setColumn('password', 'string', 128, array('type' => 'string', 'notblank' => true, 'notnull' => true, 'length' => '128')); - $table->setColumn('first_name', 'string', 32, array('type' => 'string', 'length' => '32')); - $table->setColumn('last_name', 'string', 32, array('type' => 'string', 'length' => '32')); - $table->setColumn('email', 'string', 200, array('type' => 'string', 'email' => true, 'notnull' => true, 'notblank' => true, 'unique' => true, 'length' => '200')); - $table->setColumn('is_staff', 'boolean', null, array('type' => 'boolean', 'notnull' => true, 'default' => false)); - $table->setColumn('is_active', 'boolean', null, array('type' => 'boolean', 'notnull' => true, 'default' => false)); - $table->setColumn('is_superuser', 'boolean', null, array('type' => 'boolean', 'notnull' => true, 'default' => false)); - $table->setColumn('last_login', 'timestamp', null, array('type' => 'timestamp')); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasMany('Role', 'Roles', array('refClass' => 'UserRole', 'local' => 'user_id', 'foreign' => 'role_id')); - $table->hasMany('Permission', 'Permissions', array('refClass' => 'UserPermission', 'local' => 'user_id', 'foreign' => 'permission_id')); - $table->hasMany('UserRole', '', array('local' => 'id', 'foreign' => 'user_id')); - $table->hasMany('UserPermission', '', array('local' => 'id', 'foreign' => 'user_id')); - $table->addTemplate(new IPF_ORM_Template_Timestampable()); - } - - public static function table() - { - return IPF_ORM::getTable('User'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('User')->createQuery($alias); - } -} \ No newline at end of file diff --git a/ipf/auth/models/_generated/BaseUserPermission.php b/ipf/auth/models/_generated/BaseUserPermission.php deleted file mode 100644 index 198ac96..0000000 --- a/ipf/auth/models/_generated/BaseUserPermission.php +++ /dev/null @@ -1,37 +0,0 @@ -setTableName('auth_user_permission'); - $table->setColumn('user_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setColumn('permission_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasOne('User', '', array('local' => 'user_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - $table->hasOne('Permission', '', array('local' => 'permission_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - } - - public static function table() - { - return IPF_ORM::getTable('UserPermission'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('UserPermission')->createQuery($alias); - } -} \ No newline at end of file diff --git a/ipf/auth/models/_generated/BaseUserRole.php b/ipf/auth/models/_generated/BaseUserRole.php deleted file mode 100644 index 9297d16..0000000 --- a/ipf/auth/models/_generated/BaseUserRole.php +++ /dev/null @@ -1,37 +0,0 @@ -setTableName('auth_user_role'); - $table->setColumn('user_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setColumn('role_id', 'integer', null, array('type' => 'integer', 'primary' => true)); - $table->setOption('type', 'INNODB'); - $table->setOption('collate', 'utf8_unicode_ci'); - $table->setOption('charset', 'utf8'); - - } - - public static function setUp(IPF_ORM_Table $table) - { - $table->hasOne('User', '', array('local' => 'user_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - $table->hasOne('Role', '', array('local' => 'role_id', 'foreign' => 'id', 'onDelete' => 'CASCADE')); - } - - public static function table() - { - return IPF_ORM::getTable('UserRole'); - } - - public static function query($alias='') - { - return IPF_ORM::getTable('UserRole')->createQuery($alias); - } -} \ No newline at end of file -- 2.49.0