diff --git a/resources/inc/class.bo_acl.inc.php b/resources/inc/class.resources_acl_bo.inc.php similarity index 90% rename from resources/inc/class.bo_acl.inc.php rename to resources/inc/class.resources_acl_bo.inc.php index 91db963b10..03eca63b8e 100755 --- a/resources/inc/class.bo_acl.inc.php +++ b/resources/inc/class.resources_acl_bo.inc.php @@ -18,7 +18,7 @@ use EGroupware\Api\Acl; * Current rights and the ones inherited from parents get ORed together, * while for admins the "closest" cat-admin will be used. */ -class bo_acl +class resources_acl_bo { var $acl; var $start = 0; @@ -30,6 +30,9 @@ class bo_acl var $debug; var $use_session = False; + const CAT_ADMIN = 64; + const DIRECT_BOOKING = 128; + const CAL_READ = 256; /** * Instance of categories class for resources * @@ -45,10 +48,6 @@ class bo_acl */ function __construct($session=False, $user=null) { - define('EGW_ACL_CAT_ADMIN',64); - define('EGW_ACL_DIRECT_BOOKING',128); - define('EGW_ACL_CALREAD',256); - $this->egw_cats = new Api\Categories($user, 'resources'); $this->debug = False; @@ -73,23 +72,11 @@ class bo_acl } } - /** - * PHP4 constructor - * - * @param boolean $session - * @deprecated use __construct() - * @return bo_acl - */ - function bo_acl($session=False) - { - self::__construct($session); - } - /** * get list of cats where current user has given rights * * @author Cornelius Weiss - * @param int $perm_type one of Acl::READ, Acl::ADD, Acl::EDIT, Acl::DELETE, EGW_ACL_DIRECT_BOOKING + * @param int $perm_type one of Acl::READ, Acl::ADD, Acl::EDIT, Acl::DELETE, self::DIRECT_BOOKING * @param int $parent_id=0 cat_id of parent to return only children of that category * @return array cat_id => cat_name * TODO mark subcats and so on! @@ -141,7 +128,7 @@ class bo_acl $cat_rights = self::get_rights($cat_id); foreach ($cat_rights as $userid => $right) { - if ($right & EGW_ACL_CAT_ADMIN) + if ($right & self::CAT_ADMIN) { return $userid; } @@ -189,7 +176,7 @@ class bo_acl /** * checks one of the following rights for current user: * - * Acl::READ, Acl::ADD, Acl::EDIT, Acl::DELETE, EGW_ACL_DIRECT_BOOKING + * Acl::READ, Acl::ADD, Acl::EDIT, Acl::DELETE, self::DIRECT_BOOKING * * @param int $cat_id * @param int $right @@ -244,7 +231,7 @@ class bo_acl $this->limit = $data['limit']; } - function set_rights($cat_id,$read,$write,$calread,$calbook,$admin) + public static function set_rights($cat_id,$read,$write,$calread,$calbook,$admin) { // Clear cache unset(self::$permissions[$cat_id]); @@ -263,8 +250,8 @@ class bo_acl $rights = false; $rights = in_array($account_id,$readcat) ? ($rights | Acl::READ) : false; $rights = in_array($account_id,$writecat) ? ($rights | Acl::READ | Acl::ADD | Acl::EDIT | Acl::DELETE): $rights; - $rights = in_array($account_id,$calreadcat) ? ($rights | EGW_ACL_CALREAD) : $rights; - $rights = in_array($account_id,$calbookcat) ? ($rights | EGW_ACL_DIRECT_BOOKING | EGW_ACL_CALREAD) : $rights; + $rights = in_array($account_id,$calreadcat) ? ($rights | self::CAL_READ) : $rights; + $rights = in_array($account_id,$calbookcat) ? ($rights | self::DIRECT_BOOKING | self::CAL_READ) : $rights; $rights = in_array($account_id,$admincat) ? ($rights = 511) : $rights; if ($rights) { diff --git a/resources/inc/class.resources_acl_ui.inc.php b/resources/inc/class.resources_acl_ui.inc.php new file mode 100755 index 0000000000..2e35b32194 --- /dev/null +++ b/resources/inc/class.resources_acl_ui.inc.php @@ -0,0 +1,255 @@ + true, + 'edit' => true, + ); + + public static $acl_map = array( + 'read' => Acl::READ, + 'write' => Acl::ADD, + 'calread' => resources_acl_bo::CAL_READ, + 'calwrite' => resources_acl_bo::DIRECT_BOOKING + ); + + function __construct() + { + $this->bo = new resources_acl_bo(True); + } + + /** + * Display a list of categories with ACL + * + * @param Array $content Returned content from etemplate + */ + public function index($content = array()) + { + if (!$GLOBALS['egw']->acl->check('run',1,'admin')) + { + $this->deny(); + } + + $content['nm'] = array( + 'get_rows' => 'resources.resources_acl_ui.get_rows', // I method/callback to request the data for the rows eg. 'notes.bo.get_rows' + 'no_search' => True, + 'no_filter' => True, // I disable the 1. filter + 'no_filter2' => True, // I disable the 2. filter (params are the same as for filter) + 'no_cat' => True, // I disable the cat-selectbox + 'row_id' => 'id', // I key into row content to set it's value as row-id, eg. 'id' + 'parent_id' => 'parent',// I key into row content of children linking them to their parent, also used as col_filter to query children + 'dataStorePrefix'=> 'categories',// Avoid conflict with user list when in admin + 'actions' => $this->get_actions(), // I array with actions, see nextmatch_widget::egw_actions + 'placeholder_actions' => array('add') // I Array Optional list of actions allowed on the placeholder. If not provided, it's ["add"]. + ); + $template = new Etemplate('resources.acl'); + $GLOBALS['egw_info']['flags']['app_header'] = $GLOBALS['egw_info']['apps']['resources']['title'] . ' - ' . lang('Configure Access Permissions'); + + $template->exec(__METHOD__, $content, $sel_options, $readonlys); + } + + protected function get_actions($appname='resources') { + + $actions = array( + 'open' => array( // does edit if allowed, otherwise view + 'caption' => 'Open', + 'default' => true, + 'allowOnMultiple' => false, + 'url' => 'menuaction=resources.resources_acl_ui.edit&cat_id=$id', + 'popup' => '600x420', + 'group' => $group=1, + ), + 'add' => array( + 'caption' => 'Add', + 'allowOnMultiple' => false, + 'icon' => 'new', + 'url' => 'menuaction=admin.admin_categories.edit&appname=resources', + 'popup' => '600x380', + 'group' => $group, + ), + ); + + return $actions; + } + + /** + * query rows for the nextmatch widget + * + * @param array $query with keys 'start', 'search', 'order', 'sort', 'col_filter' + * @param array &$rows returned rows/competitions + * @param array &$readonlys eg. to disable buttons based on Acl, not use here, maybe in a derived class + * @return int total number of rows + */ + public function get_rows(&$query,&$rows,&$readonlys) + { + + Api\Cache::setSession('resources','acl-nm',$query); + + if($query['filter'] > 0 || $query['col_filter']['owner']) + { + $owner = $query['col_filter']['owner'] ? $query['col_filter']['owner'] : $query['filter']; + } + + $cats = new Api\Categories($owner,'resources'); + $parent = $query['search'] ? false : 0; + $rows = $cats->return_sorted_array($query['start'],false,$query['search'],$query['sort'],$query['order'],'all_no_acl',$parent,true,$filter); + $count = $cats->total_records; + + + $config = Api\Config::read('resources'); + $location_cats = $config['location_cats'] ? explode(',', $config['location_cats']) : array(); + + foreach($rows as $key => &$row) + { + $row['owner'] = explode(',',$row['owner']); + + $row['level_spacer'] = str_repeat('    ',$row['level']); + $row['location'] = (in_array($row['id'], $location_cats)); + + if ($row['data']['icon']) + { + $row['icon_url'] = $GLOBALS['egw_info']['server']['webserver_url']. resources_bo::ICON_PATH.'/'.$row['data']['icon']; + } + + $row['subs'] = count($row['children']); + + $row['class'] = 'level'.$row['level']; + + foreach(self::$acl_map as $field => $acl) + { + $row[$field] = $GLOBALS['egw']->acl->get_ids_for_location('L'.$row['id'], $acl, 'resources'); + } + + } + $rows = $count <= $query['num_rows'] ? array_values($rows) : array_slice($rows, $query['start'], $query['num_rows']); + + return $count; + } + + /** + * Edit / add a category ACL + * + * @param array $content = null + * @param string $msg = '' + */ + public function edit(array $content=null,$msg='') + { + if (!$GLOBALS['egw']->acl->check('run',1,'admin')) + { + $this->deny(); + } + if (!isset($content)) + { + if (!(isset($_GET['cat_id']) && $_GET['cat_id'] > 0 && + ($content = Categories::read($_GET['cat_id'])))) + { + $content = array('data' => array()); + } + } + elseif ($content['button']) + { + $cats = new Categories($content['owner'] ? $content['owner'] : Categories::GLOBAL_ACCOUNT,'resources'); + + list($button) = each($content['button']); + unset($content['button']); + + $refresh_app = 'admin'; + + switch($button) + { + case 'save': + case 'apply': + if(is_array($content['owner'])) $content['owner'] = implode(',',$content['owner']); + if($content['owner'] == '') $content['owner'] = 0; + if ($content['id']) + { + + $data = $cats->id2name($content['id'],'data'); + try { + $cats->edit($content); + resources_acl_bo::set_rights( + $content['id'], $content['read'], $content['write'], $content['calread'], $content['calwrite'], null + ); + $msg = lang('Category saved.'); + } + catch (Api\Exception\WrongUserinput $e) + { + $msg = lang('Unwilling to save category with current settings. Check for inconsistency:').$e->getMessage(); // display conflicts etc. + } + } + else + { + $msg = lang('Permission denied!'); + unset($button); + } + if ($button == 'save') + { + Framework::refresh_opener($msg, $refresh_app, $content['id'], 'update', 'admin'); + Framework::window_close(); + } + break; + } + // This should probably refresh the application $this->appname in the target tab $refresh_app, but that breaks pretty much everything + Framework::refresh_opener($msg, $refresh_app, $content['id'], 'update', 'resources'); + } + + $content['appname'] = 'resources'; + if($content['data']['icon']) + { + $content['icon_url'] = $content['base_url'] . $content['data']['icon']; + } + + // Make sure $content['owner'] is an array otherwise it wont show up values in the multiselectbox + if($content['owner'] == 0) + { + unset($content['owner']); + } + else if (!is_array($content['owner'])) + { + $content['owner'] = explode(',',$content['owner']); + } + + foreach(self::$acl_map as $field => $acl) + { + $content[$field] = $GLOBALS['egw']->acl->get_ids_for_location('L'.$content['id'], $acl, 'resources'); + } + + // Location + $config = Api\Config::read('resources'); + $content['location'] = in_array($content['id'],$config['location_cats'] ? explode(',', $config['location_cats']) : array()); + + $tmpl = new Etemplate('resources.acl_edit'); + $tmpl->exec('resources.resources_acl_ui.edit',$content,$sel_options,$readonlys,$content,2); + } + + function deny() + { + echo '

'.lang('Access not permitted').'
'; + exit(True); + } +} diff --git a/resources/inc/class.resources_bo.inc.php b/resources/inc/class.resources_bo.inc.php index b7be48b973..2d044dd5e7 100755 --- a/resources/inc/class.resources_bo.inc.php +++ b/resources/inc/class.resources_bo.inc.php @@ -41,7 +41,7 @@ class resources_bo /** * Instance of resources Acl class * - * @var bo_acl + * @var resources_acl_bo */ var $acl; /** @@ -84,13 +84,13 @@ class resources_bo function __construct($user=null) { $this->so = new resources_so(); - $this->acl = CreateObject('resources.bo_acl', $user); + $this->acl = new resources_acl_bo($user); $this->cats = $this->acl->egw_cats; $this->cal_right_transform = array( - EGW_ACL_CALREAD => Acl::READ, - EGW_ACL_DIRECT_BOOKING => Acl::READ | Acl::ADD | Acl::EDIT | Acl::DELETE, - EGW_ACL_CAT_ADMIN => Acl::READ | Acl::ADD | Acl::EDIT | Acl::DELETE, + resources_acl_bo::CAL_READ => Acl::READ, + resources_acl_bo::DIRECT_BOOKING => Acl::READ | Acl::ADD | Acl::EDIT | Acl::DELETE, + resources_acl_bo::CAT_ADMIN => Acl::READ | Acl::ADD | Acl::EDIT | Acl::DELETE, ); } @@ -231,7 +231,7 @@ class resources_bo $resource['class'] .= 'no_book '; $resource['class'] .= 'no_view_calendar '; } - if(!$this->acl->is_permitted($resource['cat_id'],EGW_ACL_CALREAD)) + if(!$this->acl->is_permitted($resource['cat_id'],resources_acl_bo::CAL_READ)) { $readonlys["calendar[$resource[res_id]]"] = true; $resource['class'] .= 'no_view_calendar '; @@ -560,7 +560,7 @@ class resources_bo { return false; } - return $this->acl->is_permitted($data['cat_id'],EGW_ACL_DIRECT_BOOKING) ? A : U; + return $this->acl->is_permitted($data['cat_id'],resources_acl_bo::DIRECT_BOOKING) ? A : U; } /** diff --git a/resources/inc/class.resources_hooks.inc.php b/resources/inc/class.resources_hooks.inc.php index b144f359cb..b5c22fb212 100644 --- a/resources/inc/class.resources_hooks.inc.php +++ b/resources/inc/class.resources_hooks.inc.php @@ -24,7 +24,7 @@ class resources_hooks { function admin_prefs_sidebox($args) { - $this->acl = CreateObject('resources.bo_acl'); + $this->acl = new resources_acl_bo(); $appname = 'resources'; $location = is_array($args) ? $args['location'] : $args; @@ -59,7 +59,7 @@ class resources_hooks 'appname' => $appname, 'global_cats'=> true)), 'Configure Access Permissions' => Egw::link('/index.php', - 'menuaction=resources.ui_acl.acllist'), + 'menuaction=resources.resources_acl_ui.index&ajax=true'), 'Custom Fields'=>egw::link('/index.php', 'menuaction=admin.customfields.index&appname=resources'), ); @@ -142,7 +142,7 @@ class resources_hooks 'parent' => 0 )); $admin = -2; - ExecMethod2('resources.bo_acl.set_rights', $new_cat_id, array($admin), array($admin), array($admin), array($admin),array($admin)); + resources_acl_bo::set_rights($new_cat_id, array($admin), array($admin), array($admin), array($admin),array($admin)); } } } diff --git a/resources/inc/class.resources_import_csv.inc.php b/resources/inc/class.resources_import_csv.inc.php index 0c32e5f107..8a126282be 100644 --- a/resources/inc/class.resources_import_csv.inc.php +++ b/resources/inc/class.resources_import_csv.inc.php @@ -38,7 +38,7 @@ class resources_import_csv extends importexport_basic_import_csv { $this->bo = new resources_bo(); // For adding ACLs - $this->acl_bo = CreateObject('resources.bo_acl',True); + $this->acl_bo = new resources_acl_bo(True); // For checking categories $this->start_time = time(); diff --git a/resources/inc/class.ui_acl.inc.php b/resources/inc/class.ui_acl.inc.php deleted file mode 100755 index b082601ade..0000000000 --- a/resources/inc/class.ui_acl.inc.php +++ /dev/null @@ -1,215 +0,0 @@ - True, - ); - - function ui_acl() - { - $this->bo = createobject('resources.bo_acl',True); - $this->nextmatchs = createobject('phpgwapi.nextmatchs'); - $this->start = $this->bo->start; - $this->query = $this->bo->query; - $this->order = $this->bo->order; - $this->sort = $this->bo->sort; - $this->cat_id = $this->bo->cat_id; - } - - function acllist() - { - if (!$GLOBALS['egw']->acl->check('run',1,'admin')) - { - $this->deny(); - } - - if ($_POST['btnDone']) - { - Egw::redirect_link('/admin/index.php'); - } - - echo $GLOBALS['egw']->framework->header(); - echo $GLOBALS['egw']->framework->navbar(); - - if ($_POST['btnSave']) - { - foreach($_POST['catids'] as $cat_id) - { - $this->bo->set_rights($cat_id,$_POST['inputread'][$cat_id],$_POST['inputwrite'][$cat_id], - $_POST['inputcalread'][$cat_id],$_POST['inputcalbook'][$cat_id],$_POST['inputadmin'][$cat_id]); - } - Api\Config::save_value('location_cats', implode(',', $_POST['location_cats']), 'resources'); - } - $template =& CreateObject('phpgwapi.Template',EGW_APP_TPL); - $template->set_file(array('acl' => 'acl.tpl')); - $template->set_block('acl','cat_list','Cblock'); - $template->set_var(array( - 'title' => $GLOBALS['egw_info']['apps']['resources']['title'] . ' - ' . lang('Configure Access Permissions'), - //'lang_search' => lang('Search'), - 'lang_save' => lang('Save'), - 'lang_done' => lang('Done'), - 'lang_read' => lang('Read permissions'), - 'lang_write' => lang('Write permissions'), - 'lang_implies_read' => lang('implies read permission'), - 'lang_calread' => lang('Read Calendar permissions'), - 'lang_calbook' => lang('Direct booking permissions'), - 'lang_implies_book' => lang('implies booking permission'), - 'lang_cat_admin' => lang('Categories admin'), - 'lang_locations_rooms' => lang('Locations / rooms'), - )); - - $left = '';//$this->nextmatchs->left('/index.php',$this->start,$this->bo->catbo->total_records,'menuaction=resources.ui_acl.acllist'); - $right = '';//$this->nextmatchs->right('/index.php',$this->start,$this->bo->catbo->total_records,'menuaction=resources.ui_acl.acllist'); - - $template->set_var(array( - 'left' => $left, - 'right' => $right, - 'lang_showing' => $this->nextmatchs->show_hits($this->bo->catbo->total_records,$this->start), - 'th_bg' => $GLOBALS['egw_info']['theme']['th_bg'], - 'sort_cat' => $this->nextmatchs->show_sort_order( - $this->sort,'cat_name','cat_name','/index.php',lang('Category'),'&menuaction=resources.ui_acl.acllist' - ), - //'query' => $this->query, - )); - - if ($this->bo->cats) - { - $config = Api\Config::read('resources'); - $location_cats = $config['location_cats'] ? explode(',', $config['location_cats']) : array(); - foreach($this->bo->cats as $cat) - { - $this->rights = $this->bo->get_rights($cat['id']); - - $tr_color = $this->nextmatchs->alternate_row_color($tr_color); - $template->set_var(array( - 'tr_color' => $tr_color, - 'catname' => $cat['name'], - 'catid' => $cat['id'], - 'read' => $this->selectlist(Acl::READ), - 'write' => $this->selectlist(Acl::ADD), - 'calread' => $this->selectlist(EGW_ACL_CALREAD), - 'calbook' =>$this->selectlist(EGW_ACL_DIRECT_BOOKING), - 'admin' => ''.$this->selectlist(EGW_ACL_CAT_ADMIN,true), - 'location_checked' => in_array($cat['id'], $location_cats) ? 'checked="1"' : '', - )); - $template->parse('Cblock','cat_list',True); - } - } - $template->pfp('out','acl',True); - echo $GLOBALS['egw']->framework->footer(); - } - - function selectlist($right,$users_only=false) - { - static $accountList=null; - static $groupList=null; - switch($GLOBALS['egw_info']['user']['preferences']['common']['account_display']) - { - case 'firstname': - case 'firstall': - $order = 'n_given,n_family'; - break; - case 'lastall': - case 'lastname': - $order = 'n_family,n_given'; - break; - default: - $order = 'account_lid,n_family,n_given'; - break; - } - if (is_null($accountList)) - { - $accountList = $GLOBALS['egw']->accounts->search(array( - 'type' => 'accounts', - 'order' => $order, - )); - uasort($accountList,array($this,($order=='n_given,n_family'?"sortByNGiven":($order=='n_family,n_given'?"sortByNLast":"sortByLid")))); - $resultList = $accountList; - } - else - { - $resultList = $accountList; - } - if (is_null($groupList) && $users_only==false) - { - $groupList = $GLOBALS['egw']->accounts->search(array( - 'type' => 'groups', - 'order' => 'account_lid', - )); - uasort($groupList,array($this,"sortByLid")); - } - if (count($groupList)>0 && $users_only==false) - { - foreach ($groupList as $k => $val) - { - $resultList[$k] = $val; - } - } - foreach ($resultList as $account) - { - $selectlist .= '' . "\n"; - } - return $selectlist; - } - - function sortByNGiven($a,$b) - { - // 0, 1 und -1 - $rv = strcasecmp($a['account_firstname'], $b['account_firstname']); - if ($rv==0) $rv = strcasecmp($a['account_lastname'], $b['account_lastname']); - if ($rv==0) $rv = strcasecmp($a['account_lid'], $b['account_lid']); - return $rv; - } - - function sortByNLast($a,$b) - { - // 0, 1 und -1 - $rv = strcasecmp($a['account_lastname'], $b['account_lastname']); - if ($rv==0) $rv = strcasecmp($a['account_firstname'], $b['account_firstname']); - if ($rv==0) $rv = strcasecmp($a['account_lid'], $b['account_lid']); - return $rv; - } - - function sortByLid($a,$b) - { - // 0, 1 und -1 - return strcasecmp($a['account_lid'], $b['account_lid']); - } - - function deny() - { - echo '

'.lang('Access not permitted').'
'; - exit(True); - } -} diff --git a/resources/templates/default/acl.xet b/resources/templates/default/acl.xet new file mode 100644 index 0000000000..cd42587dc3 --- /dev/null +++ b/resources/templates/default/acl.xet @@ -0,0 +1,54 @@ + + + + + + diff --git a/resources/templates/default/acl_edit.xet b/resources/templates/default/acl_edit.xet new file mode 100644 index 0000000000..c8728ab6bf --- /dev/null +++ b/resources/templates/default/acl_edit.xet @@ -0,0 +1,68 @@ + + + + + + diff --git a/resources/templates/default/app.css b/resources/templates/default/app.css index 494501fef5..69854fc427 100644 --- a/resources/templates/default/app.css +++ b/resources/templates/default/app.css @@ -13,4 +13,13 @@ div.resources_pictureFile div.progress{ position: absolute; width:226px; +} + +#resources-acl_edit .permissions { + margin: 2em 0em; + height: auto; +} + +#resources-acl_edit .permissions .th { + border-bottom: 1px solid #696969; } \ No newline at end of file diff --git a/resources/templates/pixelegg/app.css b/resources/templates/pixelegg/app.css index c340e1378f..f56b552299 100755 --- a/resources/templates/pixelegg/app.css +++ b/resources/templates/pixelegg/app.css @@ -11,6 +11,28 @@ * @package tracker * @version $Id$ */ +/** + * Styles for Resources app + * + * @version: $Id$ + */ +#resources-edit.et2_container { + width: 848px; +} +#resources-edit_res_id:before { + content: "#"; +} +div.resources_pictureFile div.progress { + position: absolute; + width: 226px; +} +#resources-acl_edit .permissions { + margin: 2em 0em; + height: auto; +} +#resources-acl_edit .permissions .th { + border-bottom: 1px solid #696969; +} #egw_fw_sidebar #egw_fw_sidemenu .egw_fw_ui_scrollarea_outerdiv .egw_fw_ui_sidemenu_entry_header_active h1 { font-size: 1.15em !important; } diff --git a/resources/templates/pixelegg/app.less b/resources/templates/pixelegg/app.less index adcdb34cd1..3bc4e6d97d 100755 --- a/resources/templates/pixelegg/app.less +++ b/resources/templates/pixelegg/app.less @@ -15,6 +15,7 @@ @import (reference) "../../../pixelegg/less/def_buttons.less"; @import (reference) "../../../pixelegg/less/def_mobile.less"; @import (reference) "../../../pixelegg/less/def_design_pattern_color_font_shadow.less"; +@import (less) "../default/app.css"; //****************************************************************** // sidebar