From 792eb18244faf5518a6c5d665bb039be46285f9d Mon Sep 17 00:00:00 2001 From: Yasen Yanev Date: Tue, 25 Mar 2014 12:57:58 +0200 Subject: [PATCH] Added user access by permission, User_Permissions behaviour --- classes/Jam/Behavior/User/Permissions.php | 3 + classes/Kohana/Controller/Tart/Layout.php | 144 ++++--- .../Kohana/Jam/Behavior/User/Permissions.php | 79 ++++ classes/Kohana/Tart.php | 394 ++++++++++-------- 4 files changed, 369 insertions(+), 251 deletions(-) create mode 100644 classes/Jam/Behavior/User/Permissions.php create mode 100644 classes/Kohana/Jam/Behavior/User/Permissions.php diff --git a/classes/Jam/Behavior/User/Permissions.php b/classes/Jam/Behavior/User/Permissions.php new file mode 100644 index 0000000..7fcf05e --- /dev/null +++ b/classes/Jam/Behavior/User/Permissions.php @@ -0,0 +1,3 @@ +request->action(), $this->access); - - if ($access === 'private' AND ( ! Auth::instance()->logged_in() OR ! Tart::user_allowed($this->request->uri(), Auth::instance()->get_user()))) - { - if ( ! Auth::instance()->logged_in()) - { - $this->notify('warning', 'You must be logged in to access this page'); - } - else - { - $this->notify('warning', 'Your user does not have access to "'.$this->request->uri().'" page'); - } - - Session::instance()->set('requested_url', $this->request->uri()); - $this->redirect(Tart::uri('session', 'new')); - } - - $this->template->title = $this->title(); - $this->template->sidebar = FALSE; - } - - public function title() - { - $name = str_replace('Controller_Tart_', '', get_class($this)); - $name = ucwords(Inflector::humanize($name)); - - if ($this->request->param('id')) - { - return ucwords(Inflector::singular($name)).' - '.Inflector::humanize($this->request->action()); - } - else - { - return $name.' - '.Inflector::humanize($this->request->action()); - } - } - - public function action_batch() - { - $ids = $this->request->post('id') ?: $this->request->query('id'); - $action = $this->request->post('action') ?: $this->request->query('action'); - - $this->{'batch_'.$action}($ids); - } - - public function notify($label, $message) - { - $notifications = Session::instance()->get('tart.notifications', array()); - - $notifications[] = array('label' => $label, 'message' => $message); - Session::instance()->set('tart.notifications', $notifications); - } - - public function post($name = NULL) - { - $post = Tart_Request::post($this->request->post(), $_FILES); - - if ($name !== NULL) - return Arr::get($post, $name); - - return $post; - } -} \ No newline at end of file + const ACCESS_METHOD_PERMISSION = 'permission'; + const ACCESS_METHOD_URL = 'url'; + + public $template = 'tart/layout/template'; + public $access = 'private'; + public $access_method = self::AUTH_METHOD_URL; + public $access_permission; + + public function before() + { + parent::before(); + + $access = Auth_Jam::access($this->request->action(), $this->access); + $access_method = 'user_access_by_'.$this->access_method; + + if ($access === 'private' AND ( ! Auth::instance()->logged_in() OR ! Tart::$access_method(Auth::instance()->get_user(), $this->access_permission, $this->request->uri()))) + { + if ( ! Auth::instance()->logged_in()) + { + $this->notify('warning', 'You must be logged in to access this page'); + } + else + { + $this->notify('warning', 'Your user does not have access to "'.$this->request->uri().'" page'); + } + + Session::instance()->set('requested_url', $this->request->uri()); + $this->redirect(Tart::uri('session', 'new')); + } + + $this->template->title = $this->title(); + $this->template->sidebar = FALSE; + } + + public function title() + { + $name = str_replace('Controller_Tart_', '', get_class($this)); + $name = ucwords(Inflector::humanize($name)); + + if ($this->request->param('id')) + { + return ucwords(Inflector::singular($name)).' - '.Inflector::humanize($this->request->action()); + } + else + { + return $name.' - '.Inflector::humanize($this->request->action()); + } + } + + public function action_batch() + { + $ids = $this->request->post('id') ?: $this->request->query('id'); + $action = $this->request->post('action') ?: $this->request->query('action'); + + $this->{'batch_'.$action}($ids); + } + + public function notify($label, $message) + { + $notifications = Session::instance()->get('tart.notifications', array()); + + $notifications[] = array('label' => $label, 'message' => $message); + Session::instance()->set('tart.notifications', $notifications); + } + + public function post($name = NULL) + { + $post = Tart_Request::post($this->request->post(), $_FILES); + + if ($name !== NULL) + return Arr::get($post, $name); + + return $post; + } +} diff --git a/classes/Kohana/Jam/Behavior/User/Permissions.php b/classes/Kohana/Jam/Behavior/User/Permissions.php new file mode 100644 index 0000000..a44adcf --- /dev/null +++ b/classes/Kohana/Jam/Behavior/User/Permissions.php @@ -0,0 +1,79 @@ +id(); + + if ( ! isset($this->_permissions[$cache_key]) OR $this->_permissions[$cache_key] === NULL) + { + $res = DB::select( + array('p.name', 'permission'), + array('p.description', 'description') + ) + ->from(array('roles_users', 'ru')) + ->join(array('permissions_roles', 'pr'), 'INNER')->on('pr.role_id', '=', 'ru.role_id') + ->join(array('permissions', 'p'), 'INNER')->on('p.id', '=', 'pr.permission_id') + ->where('ru.user_id', '=', $user->id()); + + $this->_permissions[$cache_key] = $res->execute()->as_array('permission', 'description'); + } + + $data->return = $this->_permissions[$cache_key]; + $data->stop = TRUE; + } + + + public function model_call_is_superadmin(Jam_Model $user, Jam_Event_Data $data) + { + $data->return = $user->roles->has('superadmin'); + $data->stop = TRUE; + } + + public function model_call_is_admin(Jam_Model $user, Jam_Event_Data $data) + { + $data->return = $user->roles->has('admin'); + $data->stop = TRUE; + } + + + /** + * Checks if user has permission. + * + * @param mixed $permission Permission name string, perission Jam object, permission id + * @return boolean + */ + public function model_call_has_permission(Jam_Model $user, Jam_Event_Data $data, $permission) + { + if ($permission instanceof Model_Permission) + { + $permission = $permission->name(); + } + elseif (is_numeric($permission)) + { + $permission = Jam::factory('permission', $permission)->name(); + } + + if ($user->is_superadmin()) + { + $data->return = TRUE; + $data->stop = TRUE; + } + + $data->return = array_key_exists($permission, $user->permissions()); + $data->stop = TRUE; + } +} diff --git a/classes/Kohana/Tart.php b/classes/Kohana/Tart.php index 6ab6f32..de5b4e5 100644 --- a/classes/Kohana/Tart.php +++ b/classes/Kohana/Tart.php @@ -9,185 +9,215 @@ */ abstract class Kohana_Tart { - public static function convert_to_class($name) - { - return str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))); - } - - public static function to_sentence(array $arr) - { - if ( ! is_array($arr)) - return (string) $arr; - - $length = count($arr); - switch ($length) - { - case 0: - return ''; - case 1: - return (string) $arr[0]; - case 2: - return $arr[0].' and '.$arr[1]; - default: - return join(', ', array_slice($arr, 0, -2)).', '.$arr[$length-2].' and '.$arr[$length-1]; - } - } - - public static function filter(array $data, array $items = NULL) - { - return new Tart_Filter($data, $items); - } - - public static function index(Jam_Query_Builder_Collection $collection, $offset = 0, array $items = array()) - { - return new Tart_Index($collection, $offset, $items); - } - - public static function table($collection = array(), array $items = array()) - { - return new Tart_Table($collection, $items); - } - - public static function pagination($total = 0, $offset = 0) - { - return new Tart_Pagination($total, $offset); - } - - public static function date_range($start = NULL, $end = NULL, $period = NULL) - { - return new Tart_Date_Range($start, $end, $period); - } - - public static function stats_widget($name, Tart_Date_Range $range = NULL) - { - $class = 'Stats_Widget_'.Tart::convert_to_class($name); - return new $class($name, $range); - } - - public static function form($context = NULL, $content = NULL) - { - return new Builder_Form(NULL, NULl, $content, $context); - } - - public static function html($context = NULL, $content = NULL) - { - return new Builder_Html(NULL, NULl, $content, $context); - } - - public static function entry($name, $params = NULL, $callback = NULL) - { - $class = 'Tart_Filter_Entry_'.Tart::convert_to_class($name); - return new $class($params, $callback); - } - - public static function column($name = NULL, $callback = NULL) - { - if (is_string($name) AND ! is_callable($name)) - { - $class = 'Tart_Column_'.Tart::convert_to_class($name); - return new $class($callback); - } - else - { - return new Tart_Column($name, $callback); - } - } - - public static function category($controller) - { - return Request::initial() ? Request::initial()->param('category') : NULL; - } - - public static function allowed($url, array $allowed = array(), array $disallowed = array()) - { - foreach (array_filter(array_diff($disallowed, $allowed)) as $rule) - { - if (preg_match("#{$rule}#", $url)) - return FALSE; - } - - foreach (array_filter($allowed) as $rule) - { - if (preg_match("#{$rule}#", $url)) - return TRUE; - } - - return FALSE; - } - - public static function user_allowed($url, $user) - { - if ( ! $user) - return TRUE; - - $allowed = array(); - $disallowed = array(); - foreach ($user->roles as $role) - { - $allowed = Arr::merge($allowed, (array) $role->allowed); - $disallowed = Arr::merge($disallowed, (array) $role->disallowed); - } - - return Tart::allowed($url, $allowed, $disallowed); - } - - public static function uri($item = NULL, $action = NULL) - { - $route_name = 'tart'; - - if ($item instanceof Jam_Validated) - { - $params = array('controller' => Inflector::plural($item->meta()->model())); - - if ($item->loaded()) - { - $params['id'] = $item->id(); - } - - if (is_array($action)) - { - $params = Arr::merge($params, $action); - } - elseif ($action) - { - $params['action'] = $action; - } - - if ( ! $action OR (is_array($action) AND ! isset($action['action']))) - { - $params['action'] = $item->loaded() ? 'edit' : 'new'; - } - - $params['category'] = Arr::get($params, 'category', Tart::category($params['controller'])); - - if ($params['category']) - { - $route_name = 'tart_category'; - } - - return Route::url($route_name, $params); - } - else - { - $params = array('controller' => $item); - - if (is_array($action)) - { - $params = Arr::merge($params, $action); - } - elseif ($action) - { - $params['action'] = $action; - } - - $params['category'] = Arr::get($params, 'category', Tart::category($params['controller'])); - - if ($params['category']) - { - $route_name = 'tart_category'; - } - - return Route::url($route_name, $params); - } - } -} \ No newline at end of file + public static function convert_to_class($name) + { + return str_replace(' ', '_', ucwords(str_replace('_', ' ', $name))); + } + + public static function to_sentence(array $arr) + { + if ( ! is_array($arr)) + return (string) $arr; + + $length = count($arr); + switch ($length) + { + case 0: + return ''; + case 1: + return (string) $arr[0]; + case 2: + return $arr[0].' and '.$arr[1]; + default: + return join(', ', array_slice($arr, 0, -2)).', '.$arr[$length-2].' and '.$arr[$length-1]; + } + } + + public static function filter(array $data, array $items = NULL) + { + return new Tart_Filter($data, $items); + } + + public static function index(Jam_Query_Builder_Collection $collection, $offset = 0, array $items = array()) + { + return new Tart_Index($collection, $offset, $items); + } + + public static function table($collection = array(), array $items = array()) + { + return new Tart_Table($collection, $items); + } + + public static function pagination($total = 0, $offset = 0) + { + return new Tart_Pagination($total, $offset); + } + + public static function date_range($start = NULL, $end = NULL, $period = NULL) + { + return new Tart_Date_Range($start, $end, $period); + } + + public static function stats_widget($name, Tart_Date_Range $range = NULL) + { + $class = 'Stats_Widget_'.Tart::convert_to_class($name); + return new $class($name, $range); + } + + public static function form($context = NULL, $content = NULL) + { + return new Builder_Form(NULL, NULl, $content, $context); + } + + public static function html($context = NULL, $content = NULL) + { + return new Builder_Html(NULL, NULl, $content, $context); + } + + public static function entry($name, $params = NULL, $callback = NULL) + { + $class = 'Tart_Filter_Entry_'.Tart::convert_to_class($name); + return new $class($params, $callback); + } + + public static function column($name = NULL, $callback = NULL) + { + if (is_string($name) AND ! is_callable($name)) + { + $class = 'Tart_Column_'.Tart::convert_to_class($name); + return new $class($callback); + } + else + { + return new Tart_Column($name, $callback); + } + } + + public static function category($controller) + { + return Request::initial() ? Request::initial()->param('category') : NULL; + } + + public static function allowed($url, array $allowed = array(), array $disallowed = array()) + { + foreach (array_filter(array_diff($disallowed, $allowed)) as $rule) + { + if (preg_match("#{$rule}#", $url)) + return FALSE; + } + + foreach (array_filter($allowed) as $rule) + { + if (preg_match("#{$rule}#", $url)) + return TRUE; + } + + return FALSE; + } + + /** + * @deprecated Use Kohana_Tart_Layout::user_access_by_url instead. + * @param $url + * @param $user + * @return bool + */ + public static function user_allowed($url, $user = NULL) + { + if ( ! $user) + return TRUE; + + $allowed = array(); + $disallowed = array(); + foreach ($user->roles as $role) + { + $allowed = Arr::merge($allowed, (array) $role->allowed); + $disallowed = Arr::merge($disallowed, (array) $role->disallowed); + } + + return Tart::allowed($url, $allowed, $disallowed); + } + + public static function user_access_by_url($user = NULL, $permission = NULL, $url) + { + if ( ! $user) + return TRUE; + + $allowed = array(); + $disallowed = array(); + foreach ($user->roles as $role) + { + $allowed = Arr::merge($allowed, (array) $role->allowed); + $disallowed = Arr::merge($disallowed, (array) $role->disallowed); + } + + return Tart::allowed($url, $allowed, $disallowed); + } + + public static function user_access_by_permission($user = NULL, $permission, $url = NULL) + { + if ( ! $user) + return TRUE; + + return $user->has_permission($permission); + } + + public static function uri($item = NULL, $action = NULL) + { + $route_name = 'tart'; + + if ($item instanceof Jam_Validated) + { + $params = array('controller' => Inflector::plural($item->meta()->model())); + + if ($item->loaded()) + { + $params['id'] = $item->id(); + } + + if (is_array($action)) + { + $params = Arr::merge($params, $action); + } + elseif ($action) + { + $params['action'] = $action; + } + + if ( ! $action OR (is_array($action) AND ! isset($action['action']))) + { + $params['action'] = $item->loaded() ? 'edit' : 'new'; + } + + $params['category'] = Arr::get($params, 'category', Tart::category($params['controller'])); + + if ($params['category']) + { + $route_name = 'tart_category'; + } + + return Route::url($route_name, $params); + } + else + { + $params = array('controller' => $item); + + if (is_array($action)) + { + $params = Arr::merge($params, $action); + } + elseif ($action) + { + $params['action'] = $action; + } + + $params['category'] = Arr::get($params, 'category', Tart::category($params['controller'])); + + if ($params['category']) + { + $route_name = 'tart_category'; + } + + return Route::url($route_name, $params); + } + } +}