diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php index 365ff4ed1c..8b8f438419 100644 --- a/calendar/inc/class.calendar_bo.inc.php +++ b/calendar/inc/class.calendar_bo.inc.php @@ -22,6 +22,10 @@ if (!defined('ACL_TYPE_IDENTIFER')) // used to mark ACL-values for the debug_mes */ define('EGW_ACL_READ_FOR_PARTICIPANTS',EGW_ACL_CUSTOM_1); define('EGW_ACL_FREEBUSY',EGW_ACL_CUSTOM_2); +/** + * Allows to invite an other user (if configured to be used!) + */ +define('EGW_ACL_INVITE',EGW_ACL_CUSTOM_3); /** * Required (!) include, as we use the MCAL_* constants, BEFORE instanciating (and therefore autoloading) the class @@ -154,6 +158,13 @@ class calendar_bo */ var $datetime; + /** + * Does a user require an extra invite grant, to be able to invite an other user, default no + * + * @var boolean + */ + public $require_acl_invite = false; + /** * Constructor */ @@ -196,7 +207,9 @@ class calendar_bo } //echo "registered resources="; _debug_array($this->resources); - $this->config = config::read('calendar'); + $this->config = config::read('calendar'); // only used for horizont, regular calendar config is under phpgwapi + + $this->require_acl_invite = $GLOBALS['egw_info']['server']['require_acl_invite']; } /** @@ -333,6 +346,8 @@ class calendar_bo // for groups we have to include the members if ($GLOBALS['egw']->accounts->get_type($user) == 'g') { + if ($params['filter'] == 'no-enum-groups') continue; + $members = $GLOBALS['egw']->accounts->member($user); if (is_array($members)) { @@ -362,6 +377,11 @@ class calendar_bo } } } + // replace (by so not understood filter 'no-enum-groups' with 'default' filter + if ($params['filter'] == 'no-enum-groups') + { + $params['filter'] = 'default'; + } // if we have no grants from the given user(s), we directly return no events / an empty array, // as calling the so-layer without users would give the events of all users (!) if (!count($users)) diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index 6718b68561..995ed61116 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -119,7 +119,23 @@ class calendar_boupdate extends calendar_bo { return false; } - + if (!($new_event = !(int)$event['id'])) + { + $old_event = $this->read((int)$event['id'],null,$ignore_acl); + // if no participants are set, set them from the old event, as we might need them to update recuring events + if (!isset($event['participants'])) $event['participants'] = $old_event['participants']; + //echo "old $event[id]="; _debug_array($old_event); + } + else + { + $event['created'] = $this->now_su; + $event['creator'] = $GLOBALS['egw_info']['user']['account_id']; + } + // do we need to check, if user is allowed to invite the invited participants + if ($this->require_acl_invite && ($removed = $this->remove_no_acl_invite($event,$old_event))) + { + // todo: report removed participants back to user + } // check for conflicts only happens !$ignore_conflicts AND if start + end date are given if (!$ignore_conflicts && !$event['non_blocking'] && isset($event['start']) && isset($event['end'])) { @@ -250,18 +266,6 @@ class calendar_boupdate extends calendar_bo $event['modified'] = $this->now_su; // we are still in user-time $event['modifier'] = $GLOBALS['egw_info']['user']['account_id']; } - if (!($new_event = !(int)$event['id'])) - { - $old_event = $this->read((int)$event['id'],null,$ignore_acl); - // if no participants are set, set them from the old event, as we might need them to update recuring events - if (!isset($event['participants'])) $event['participants'] = $old_event['participants']; - //echo "old $event[id]="; _debug_array($old_event); - } - else - { - $event['created'] = $this->now_su; - $event['creator'] = $GLOBALS['egw_info']['user']['account_id']; - } //echo "saving $event[id]="; _debug_array($event); $event2save = $event; @@ -293,6 +297,53 @@ class calendar_boupdate extends calendar_bo return $cal_id; } + /** + * Remove participants current user has no right to invite + * + * @param array &$event new event + * @param array $old_event=null old event with already invited participants + * @return array removed participants because of missing invite grants + */ + public function remove_no_acl_invite(array &$event,array $old_event=null) + { + if (!$this->require_acl_invite) + { + return array(); // nothing to check, everyone can invite everyone else + } + if ($event['id'] && is_null($old_event)) + { + $old_event = $this->read($event['id']); + } + $removed = array(); + foreach($event['participants'] as $uid => $status) + { + if ((is_null($old_event) || !in_array($old_event['participants'][$uid])) && !$this->check_acl_invite($uid)) + { + unset($event['participants'][$uid]); // remove participant + $removed[] = $uid; + } + } + echo "

".__METHOD__."($event[title],".($old_event?'$old_event':'NULL').") returning ".array2string($removed)."

"; + return $removed; + } + + /** + * Check if current user is allowed to invite a given participant + * + * @param int|string $uid + * @return boolean + */ + public function check_acl_invite($uid) + { + if (!is_numeric($uid)) return true; // nothing implemented for resources so far + + if ($this->require_acl_invite == 'group' && $GLOBALS['egw']->accounts->get_type($uid) != 'g') + { + return true; // grant only required for groups + } + return $this->check_perms(EGW_ACL_INVITE,0,$uid); + } + /** * Check for added, modified or deleted participants AND notify them * @@ -1080,7 +1131,7 @@ class calendar_boupdate extends calendar_bo { $this->categories = new categories($this->user,'calendar'); } - + if($cal_id && $cal_id > 0) { // preserve categories without users read access @@ -1104,7 +1155,7 @@ class calendar_boupdate extends calendar_bo { $cat_name = trim($cat_name); $cat_id = $this->categories->name2id($cat_name, 'X-'); - + if (!$cat_id) { // some SyncML clients (mostly phones) add an X- to the category names @@ -1120,7 +1171,7 @@ class calendar_boupdate extends calendar_bo $cat_id_list[] = $cat_id; } } - + if(is_array($old_cats_preserve) && count($old_cats_preserve) > 0) { $cat_id_list = array_merge($cat_id_list, $old_cats_preserve); @@ -1149,7 +1200,7 @@ class calendar_boupdate extends calendar_bo $cat_list = array(); foreach($cat_id_list as $cat_id) { - if ($cat_id && $this->categories->check_perms(EGW_ACL_READ, $cat_id) && + if ($cat_id && $this->categories->check_perms(EGW_ACL_READ, $cat_id) && ($cat_name = $this->categories->id2name($cat_id)) && $cat_name != '--') { $cat_list[] = $cat_name; diff --git a/calendar/inc/class.calendar_ui.inc.php b/calendar/inc/class.calendar_ui.inc.php index 10183541b6..b3e1512c67 100644 --- a/calendar/inc/class.calendar_ui.inc.php +++ b/calendar/inc/class.calendar_ui.inc.php @@ -578,6 +578,13 @@ class calendar_ui } $views .= "\n"; + // hack to disable invite ACL column, if not enabled in config + if ($_GET['menuaction'] == 'preferences.uiaclprefs.index' && + (!$this->bo->require_acl_invite || $this->bo->require_acl_invite == 'groups' && !($_REQUEST['owner'] < 0))) + { + $views .= "\n"; + } + $file[++$n] = array('text' => $views,'no_lang' => True,'link' => False,'icon' => False); // special views and view-options menu @@ -696,17 +703,19 @@ class calendar_ui // Filter all or hideprivate $options = ''; foreach(array( - 'default' => lang('Not rejected'), - 'accepted' => lang('Accepted'), - 'unknown' => lang('Invitations'), - 'tentative' => lang('Tentative'), - 'rejected' => lang('Rejected'), - 'owner' => lang('Owner too'), - 'all' => lang('All incl. rejected'), - 'hideprivate' => lang('Hide private infos'), + 'default' => array(lang('Not rejected'), lang('Show all status, but rejected')), + 'accepted' => array(lang('Accepted'), lang('Show only accepted events')), + 'unknown' => array(lang('Invitations'), lang('Show only invitations, not yet accepted or rejected')), + 'tentative' => array(lang('Tentative'), lang('Show only tentative accepted events')), + 'rejected' => array(lang('Rejected'),lang('Show only rejected events')), + 'owner' => array(lang('Owner too'),lang('Show also events just owned by selected user')), + 'all' => array(lang('All incl. rejected'),lang('Show all status incl. rejected events')), + 'hideprivate' => array(lang('Hide private infos'),lang('Show all events, as if they were private')), + 'no-enum-groups' => array(lang('only group-events'),lang('Do not include events of group members')), ) as $value => $label) { - $options .= '