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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -727,7 +731,7 @@ class calendar extends rcube_plugin
|
|||
if ($numcals <= 1)
|
||||
$calendar_select = null;
|
||||
}
|
||||
|
||||
|
||||
if ($status == 'unknown') {
|
||||
$html = html::div('rsvp-status', $this->gettext('notanattendee'));
|
||||
$action = 'import';
|
||||
|
@ -738,7 +742,7 @@ class calendar extends rcube_plugin
|
|||
$action = ''; // nothing to do here
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$default_calendar = $calendar_select ? $this->get_default_calendar(true) : null;
|
||||
$this->rc->output->command('plugin.update_event_rsvp_status', array(
|
||||
'uid' => $event['uid'],
|
||||
|
@ -1974,7 +1978,15 @@ class calendar extends rcube_plugin
|
|||
*/
|
||||
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)
|
||||
$emails[] = $identity['email'];
|
||||
|
||||
|
|
|
@ -147,6 +147,16 @@ class kolab_driver extends calendar_driver
|
|||
protected function filter_calendars($writable = false, $active = false, $personal = false)
|
||||
{
|
||||
$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) {
|
||||
if (!$cal->ready) {
|
||||
continue;
|
||||
|
|
|
@ -28,14 +28,14 @@ class calendar_itip
|
|||
{
|
||||
private $rc;
|
||||
private $cal;
|
||||
private $event;
|
||||
private $sender;
|
||||
private $itip_send = false;
|
||||
|
||||
function __construct($cal)
|
||||
function __construct($cal, $identity = null)
|
||||
{
|
||||
$this->cal = $cal;
|
||||
$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'));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,14 @@
|
|||
*/
|
||||
|
||||
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
|
||||
var tab = $('<span>').attr('id', 'settingstabplugindelegation').addClass('tablink'),
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
public $task = 'login|mail|settings';
|
||||
public $task = 'login|mail|settings|calendar';
|
||||
|
||||
private $rc;
|
||||
private $engine;
|
||||
|
@ -41,10 +41,19 @@ class kolab_delegation extends rcube_plugin
|
|||
$this->require_plugin('libkolab');
|
||||
$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'));
|
||||
|
||||
// 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') {
|
||||
// delegation management interface
|
||||
$this->register_action('plugin.delegation', array($this, 'controller_ui'));
|
||||
$this->register_action('plugin.delegation-delete', 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;
|
||||
}
|
||||
|
||||
if (empty($_SESSION['delegator_uids'])) {
|
||||
if (empty($_SESSION['delegators'])) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
@ -113,7 +122,7 @@ class kolab_delegation extends rcube_plugin
|
|||
$other_ns = $storage->get_namespace('other');
|
||||
$folders = $storage->list_folders_subscribed('', '*', 'mail');
|
||||
|
||||
foreach ($_SESSION['delegator_uids'] as $uid) {
|
||||
foreach (array_keys($_SESSION['delegators']) as $uid) {
|
||||
foreach ($other_ns as $ns) {
|
||||
$folder = $ns[0] . $uid;
|
||||
if (in_array($folder, $folders) && !in_array($folder, $args['folders'])) {
|
||||
|
@ -125,6 +134,79 @@ class kolab_delegation extends rcube_plugin
|
|||
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
|
||||
*/
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
class kolab_delegation_engine
|
||||
{
|
||||
public $context;
|
||||
|
||||
private $rc;
|
||||
private $ldap_filter;
|
||||
private $ldap_delegate_field;
|
||||
|
@ -532,9 +534,8 @@ class kolab_delegation_engine
|
|||
|
||||
// for every delegator...
|
||||
foreach ($delegators as $delegator) {
|
||||
$uids[] = $delegator['imap_uid'];
|
||||
$email_arr = $delegator['email'];
|
||||
$diff = array_intersect($emails, $email_arr);
|
||||
$uids[$delegator['imap_uid']] = $email_arr = $delegator['email'];
|
||||
$diff = array_intersect($emails, $email_arr);
|
||||
|
||||
// identity with delegator's email already exist, do nothing
|
||||
if (count($diff)) {
|
||||
|
@ -545,6 +546,8 @@ class kolab_delegation_engine
|
|||
// create identities for delegator emails
|
||||
foreach ($email_arr as $email) {
|
||||
$default['email'] = $email;
|
||||
// @TODO: "Username" or "Delegatorname" or "Username on behalf of Delegatorname"
|
||||
//$default['name'] = $delegator['email'];
|
||||
$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