Delegation support in calendar event invitations handling
This commit is contained in:
parent
a24ad50619
commit
3be3065941
6 changed files with 261 additions and 16 deletions
|
@ -209,9 +209,13 @@ class calendar extends rcube_plugin
|
||||||
{
|
{
|
||||||
if (!$this->itip) {
|
if (!$this->itip) {
|
||||||
require_once($this->home . '/lib/calendar_itip.php');
|
require_once($this->home . '/lib/calendar_itip.php');
|
||||||
$this->itip = new calendar_itip($this);
|
|
||||||
|
$plugin = $this->rc->plugins->exec_hook('calendar_load_itip',
|
||||||
|
array('identity' => null));
|
||||||
|
|
||||||
|
$this->itip = new calendar_itip($this, $plugin['identity']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->itip;
|
return $this->itip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,7 +731,7 @@ class calendar extends rcube_plugin
|
||||||
if ($numcals <= 1)
|
if ($numcals <= 1)
|
||||||
$calendar_select = null;
|
$calendar_select = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($status == 'unknown') {
|
if ($status == 'unknown') {
|
||||||
$html = html::div('rsvp-status', $this->gettext('notanattendee'));
|
$html = html::div('rsvp-status', $this->gettext('notanattendee'));
|
||||||
$action = 'import';
|
$action = 'import';
|
||||||
|
@ -738,7 +742,7 @@ class calendar extends rcube_plugin
|
||||||
$action = ''; // nothing to do here
|
$action = ''; // nothing to do here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$default_calendar = $calendar_select ? $this->get_default_calendar(true) : null;
|
$default_calendar = $calendar_select ? $this->get_default_calendar(true) : null;
|
||||||
$this->rc->output->command('plugin.update_event_rsvp_status', array(
|
$this->rc->output->command('plugin.update_event_rsvp_status', array(
|
||||||
'uid' => $event['uid'],
|
'uid' => $event['uid'],
|
||||||
|
@ -1974,7 +1978,15 @@ class calendar extends rcube_plugin
|
||||||
*/
|
*/
|
||||||
private function get_user_emails()
|
private function get_user_emails()
|
||||||
{
|
{
|
||||||
$emails = array($this->rc->user->get_username());
|
$emails = array();
|
||||||
|
$plugin = $this->rc->plugins->exec_hook('calendar_user_emails', array('emails' => $emails));
|
||||||
|
$emails = $plugin['emails'];
|
||||||
|
|
||||||
|
if ($plugin['abort']) {
|
||||||
|
return $emails;
|
||||||
|
}
|
||||||
|
|
||||||
|
$emails[] = $this->rc->user->get_username();
|
||||||
foreach ($this->rc->user->list_identities() as $identity)
|
foreach ($this->rc->user->list_identities() as $identity)
|
||||||
$emails[] = $identity['email'];
|
$emails[] = $identity['email'];
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,16 @@ class kolab_driver extends calendar_driver
|
||||||
protected function filter_calendars($writable = false, $active = false, $personal = false)
|
protected function filter_calendars($writable = false, $active = false, $personal = false)
|
||||||
{
|
{
|
||||||
$calendars = array();
|
$calendars = array();
|
||||||
|
|
||||||
|
$plugin = $this->rc->plugins->exec_hook('calendar_list_filter', array(
|
||||||
|
'list' => $this->calendars, 'calendars' => $calendars,
|
||||||
|
'writable' => $writable, 'active' => $active, 'personal' => $personal,
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($plugin['abort']) {
|
||||||
|
return $plugin['calendars'];
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->calendars as $cal) {
|
foreach ($this->calendars as $cal) {
|
||||||
if (!$cal->ready) {
|
if (!$cal->ready) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -28,14 +28,14 @@ class calendar_itip
|
||||||
{
|
{
|
||||||
private $rc;
|
private $rc;
|
||||||
private $cal;
|
private $cal;
|
||||||
private $event;
|
private $sender;
|
||||||
private $itip_send = false;
|
private $itip_send = false;
|
||||||
|
|
||||||
function __construct($cal)
|
function __construct($cal, $identity = null)
|
||||||
{
|
{
|
||||||
$this->cal = $cal;
|
$this->cal = $cal;
|
||||||
$this->rc = $cal->rc;
|
$this->rc = $cal->rc;
|
||||||
$this->sender = $this->rc->user->get_identity();
|
$this->sender = $identity ? $identity : $this->rc->user->get_identity();
|
||||||
|
|
||||||
$this->cal->add_hook('smtp_connect', array($this, 'smtp_connect_hook'));
|
$this->cal->add_hook('smtp_connect', array($this, 'smtp_connect_hook'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.rcmail && rcmail.addEventListener('init', function(evt) {
|
window.rcmail && rcmail.addEventListener('init', function(evt) {
|
||||||
|
if (rcmail.env.task == 'mail') {
|
||||||
|
// set delegator context for calendar requests on invitation message
|
||||||
|
rcmail.addEventListener('requestcalendar/event', function(o) { rcmail.event_delegator_request(o); });
|
||||||
|
rcmail.addEventListener('requestcalendar/mailimportevent', function(o) { rcmail.event_delegator_request(o); });
|
||||||
|
}
|
||||||
|
else if (rcmail.env.task != 'settings')
|
||||||
|
return;
|
||||||
|
|
||||||
// add Delegation section to the list
|
// add Delegation section to the list
|
||||||
var tab = $('<span>').attr('id', 'settingstabplugindelegation').addClass('tablink'),
|
var tab = $('<span>').attr('id', 'settingstabplugindelegation').addClass('tablink'),
|
||||||
button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.delegation')
|
button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.delegation')
|
||||||
|
@ -218,3 +226,16 @@ rcube_webmail.prototype.delegate_save_complete = function(p)
|
||||||
this.enable_command('delegate-delete', false);
|
this.enable_command('delegate-delete', false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rcube_webmail.prototype.event_delegator_request = function(data)
|
||||||
|
{
|
||||||
|
if (!this.env.delegator_context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (typeof data === 'object')
|
||||||
|
data._context = this.env.delegator_context;
|
||||||
|
else
|
||||||
|
data += '&_context=' + this.env.delegator_context;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
class kolab_delegation extends rcube_plugin
|
class kolab_delegation extends rcube_plugin
|
||||||
{
|
{
|
||||||
public $task = 'login|mail|settings';
|
public $task = 'login|mail|settings|calendar';
|
||||||
|
|
||||||
private $rc;
|
private $rc;
|
||||||
private $engine;
|
private $engine;
|
||||||
|
@ -41,10 +41,19 @@ class kolab_delegation extends rcube_plugin
|
||||||
$this->require_plugin('libkolab');
|
$this->require_plugin('libkolab');
|
||||||
$this->require_plugin('kolab_auth');
|
$this->require_plugin('kolab_auth');
|
||||||
|
|
||||||
$this->add_hook('login_after', array($this, 'login_hook'));
|
// on-login delegation initialization
|
||||||
|
$this->add_hook('login_after', array($this, 'login_hook'));
|
||||||
|
// on-check-recent delegation support
|
||||||
$this->add_hook('check_recent', array($this, 'check_recent_hook'));
|
$this->add_hook('check_recent', array($this, 'check_recent_hook'));
|
||||||
|
|
||||||
|
// delegation support in Calendar plugin
|
||||||
|
$this->add_hook('message_load', array($this, 'message_load'));
|
||||||
|
$this->add_hook('calendar_user_emails', array($this, 'calendar_user_emails'));
|
||||||
|
$this->add_hook('calendar_list_filter', array($this, 'calendar_list_filter'));
|
||||||
|
$this->add_hook('calendar_load_itip', array($this, 'calendar_load_itip'));
|
||||||
|
|
||||||
if ($this->rc->task == 'settings') {
|
if ($this->rc->task == 'settings') {
|
||||||
|
// delegation management interface
|
||||||
$this->register_action('plugin.delegation', array($this, 'controller_ui'));
|
$this->register_action('plugin.delegation', array($this, 'controller_ui'));
|
||||||
$this->register_action('plugin.delegation-delete', array($this, 'controller_action'));
|
$this->register_action('plugin.delegation-delete', array($this, 'controller_action'));
|
||||||
$this->register_action('plugin.delegation-save', array($this, 'controller_action'));
|
$this->register_action('plugin.delegation-save', array($this, 'controller_action'));
|
||||||
|
@ -105,7 +114,7 @@ class kolab_delegation extends rcube_plugin
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($_SESSION['delegator_uids'])) {
|
if (empty($_SESSION['delegators'])) {
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +122,7 @@ class kolab_delegation extends rcube_plugin
|
||||||
$other_ns = $storage->get_namespace('other');
|
$other_ns = $storage->get_namespace('other');
|
||||||
$folders = $storage->list_folders_subscribed('', '*', 'mail');
|
$folders = $storage->list_folders_subscribed('', '*', 'mail');
|
||||||
|
|
||||||
foreach ($_SESSION['delegator_uids'] as $uid) {
|
foreach (array_keys($_SESSION['delegators']) as $uid) {
|
||||||
foreach ($other_ns as $ns) {
|
foreach ($other_ns as $ns) {
|
||||||
$folder = $ns[0] . $uid;
|
$folder = $ns[0] . $uid;
|
||||||
if (in_array($folder, $folders) && !in_array($folder, $args['folders'])) {
|
if (in_array($folder, $folders) && !in_array($folder, $args['folders'])) {
|
||||||
|
@ -125,6 +134,79 @@ class kolab_delegation extends rcube_plugin
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* E-mail message loading action
|
||||||
|
*/
|
||||||
|
public function message_load($args)
|
||||||
|
{
|
||||||
|
// This is a place where we detect delegate context
|
||||||
|
// So we can handle event invitations on behalf of delegator
|
||||||
|
// @TODO: should we do this only in delegators' folders?
|
||||||
|
|
||||||
|
$engine = $this->engine();
|
||||||
|
$context = $engine->delegator_context_from_message($args['object']);
|
||||||
|
|
||||||
|
if ($context) {
|
||||||
|
$this->rc->output->set_env('delegator_context', $context);
|
||||||
|
$this->include_script('kolab_delegation.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calendar::get_user_emails() handler
|
||||||
|
*/
|
||||||
|
public function calendar_user_emails($args)
|
||||||
|
{
|
||||||
|
// In delegator context we'll use delegator's addresses
|
||||||
|
// instead of current user addresses
|
||||||
|
|
||||||
|
$engine = $this->engine();
|
||||||
|
|
||||||
|
if ($context = $engine->delegator_context()) {
|
||||||
|
$args['emails'] = $_SESSION['delegators'][$context];
|
||||||
|
$args['abort'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calendar_driver::list_calendars() handler
|
||||||
|
*/
|
||||||
|
public function calendar_list_filter($args)
|
||||||
|
{
|
||||||
|
// In delegator context we'll use delegator's folders
|
||||||
|
// instead of current user folders
|
||||||
|
|
||||||
|
$engine = $this->engine();
|
||||||
|
|
||||||
|
if ($engine->delegator_context()) {
|
||||||
|
$args['calendars'] = $engine->delegator_folder_filter($args);
|
||||||
|
$args['abort'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calendar::load_itip() handler
|
||||||
|
*/
|
||||||
|
public function calendar_load_itip($args)
|
||||||
|
{
|
||||||
|
// In delegator context we'll use delegator's address/name
|
||||||
|
// for invitation responses
|
||||||
|
|
||||||
|
$engine = $this->engine();
|
||||||
|
|
||||||
|
if ($engine->delegator_context()) {
|
||||||
|
$args['identity'] = $engine->delegator_identity();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegation UI handler
|
* Delegation UI handler
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
class kolab_delegation_engine
|
class kolab_delegation_engine
|
||||||
{
|
{
|
||||||
|
public $context;
|
||||||
|
|
||||||
private $rc;
|
private $rc;
|
||||||
private $ldap_filter;
|
private $ldap_filter;
|
||||||
private $ldap_delegate_field;
|
private $ldap_delegate_field;
|
||||||
|
@ -532,9 +534,8 @@ class kolab_delegation_engine
|
||||||
|
|
||||||
// for every delegator...
|
// for every delegator...
|
||||||
foreach ($delegators as $delegator) {
|
foreach ($delegators as $delegator) {
|
||||||
$uids[] = $delegator['imap_uid'];
|
$uids[$delegator['imap_uid']] = $email_arr = $delegator['email'];
|
||||||
$email_arr = $delegator['email'];
|
$diff = array_intersect($emails, $email_arr);
|
||||||
$diff = array_intersect($emails, $email_arr);
|
|
||||||
|
|
||||||
// identity with delegator's email already exist, do nothing
|
// identity with delegator's email already exist, do nothing
|
||||||
if (count($diff)) {
|
if (count($diff)) {
|
||||||
|
@ -545,6 +546,8 @@ class kolab_delegation_engine
|
||||||
// create identities for delegator emails
|
// create identities for delegator emails
|
||||||
foreach ($email_arr as $email) {
|
foreach ($email_arr as $email) {
|
||||||
$default['email'] = $email;
|
$default['email'] = $email;
|
||||||
|
// @TODO: "Username" or "Delegatorname" or "Username on behalf of Delegatorname"
|
||||||
|
//$default['name'] = $delegator['email'];
|
||||||
$this->rc->user->insert_identity($default);
|
$this->rc->user->insert_identity($default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +587,124 @@ class kolab_delegation_engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['delegator_uids'] = $uids;
|
$_SESSION['delegators'] = $uids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets delegator context according to email message recipient
|
||||||
|
*
|
||||||
|
* @param rcube_message $message Email message object
|
||||||
|
*/
|
||||||
|
public function delegator_context_from_message($message)
|
||||||
|
{
|
||||||
|
if (empty($_SESSION['delegators'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match delegators' addresses with message To: address
|
||||||
|
// @TODO: Is this reliable enough?
|
||||||
|
// Roundcube sends invitations to every attendee separately,
|
||||||
|
// but maybe there's a software which sends with CC header or many addresses in To:
|
||||||
|
|
||||||
|
$emails = $message->get_header('to');
|
||||||
|
$emails = rcube_mime::decode_address_list($emails, null, false);
|
||||||
|
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
foreach ($_SESSION['delegators'] as $uid => $addresses) {
|
||||||
|
if (in_array($email['mailto'], $addresses)) {
|
||||||
|
return $this->context = $uid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return (set) current delegator context
|
||||||
|
*
|
||||||
|
* @return string Delegator UID
|
||||||
|
*/
|
||||||
|
public function delegator_context()
|
||||||
|
{
|
||||||
|
if (!$this->context && !empty($_SESSION['delegators'])) {
|
||||||
|
$context = rcube_utils::get_input_value('_context', rcube_utils::INPUT_GPC);
|
||||||
|
if ($context && isset($_SESSION['delegators'][$context])) {
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return identity of the current delegator
|
||||||
|
*
|
||||||
|
* @return array Identity data (name and email)
|
||||||
|
*/
|
||||||
|
public function delegator_identity()
|
||||||
|
{
|
||||||
|
if (!$this->context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$identities = $this->rc->user->list_identities();
|
||||||
|
$emails = $_SESSION['delegators'][$this->context];
|
||||||
|
|
||||||
|
foreach ($identities as $ident) {
|
||||||
|
if (in_array($ident['email'], $emails)) {
|
||||||
|
return $ident;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters list of calendars according to delegator context
|
||||||
|
*
|
||||||
|
* @param array $args Plugin hook arguments
|
||||||
|
*
|
||||||
|
* @return array List of calendars
|
||||||
|
*/
|
||||||
|
public function delegator_folder_filter($args)
|
||||||
|
{
|
||||||
|
if (empty($this->context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$storage = $this->rc->get_storage();
|
||||||
|
$other_ns = $storage->get_namespace('other');
|
||||||
|
$delim = $storage->get_hierarchy_delimiter();
|
||||||
|
$calendars = array();
|
||||||
|
|
||||||
|
// code parts derived from kolab_driver::filter_calendars()
|
||||||
|
foreach ($args['list'] as $cal) {
|
||||||
|
if (!$cal->ready) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($args['writeable'] && $cal->readonly) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($args['active'] && !$cal->storage->is_active()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($args['personal']) {
|
||||||
|
$ns = $cal->get_namespace();
|
||||||
|
$name = $cal->get_realname(); // UTF-7 IMAP folder name
|
||||||
|
|
||||||
|
if ($ns != 'other') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($other_ns as $ns) {
|
||||||
|
$folder = $ns[0] . $this->context . $delim;
|
||||||
|
if (strpos($name, $folder) !== 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$calendars[$cal->id] = $cal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $calendars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue