Resolve attendee group names to lists of individual users. Configurable by $c->enable_attendee_group_resolution (from !21)

This commit is contained in:
Frank Steinberg 2016-01-21 13:33:30 +01:00 committed by Florian Schlichting
parent 44ff0b3286
commit 3bb6cd4479
3 changed files with 84 additions and 0 deletions

View File

@ -300,6 +300,15 @@ $c->admin_email ='calendar-admin@example.com';
*/ */
// $c->allow_get_email_visibility = false; // $c->allow_get_email_visibility = false;
/**
* EXPERIMENTAL:
* If true, names of groups (prefixed with "@") given as an event attendee
* will get resolved to a list of members of that group. Note that CalDAV
* clients might get confused by this server behavior until they get
* synced again. Default: false.
*/
// $c->enable_attendee_group_resolution = true;
/*************************************************************************** /***************************************************************************
* * * *

View File

@ -50,6 +50,35 @@ function handle_freebusy_request( $ic ) {
} }
dbg_error_log( "POST", "Responding with free/busy for %d attendees", count($attendees) ); dbg_error_log( "POST", "Responding with free/busy for %d attendees", count($attendees) );
if ($c->enable_attendee_group_resolution) {
$new_attendees = array();
foreach( $attendees AS $attendee ) {
$v = $attendee->Value();
unset($localname);
if ($v == "invalid:nomail") {
$localname = $attendee->GetParameterValue("CN");
} else if ((preg_match('/^@/', $v) == 1) || (preg_match('/mailto:@/',$v) == 1)) {
$localname = preg_replace('/^.*@/', '', $v);
} else if (preg_match('/@/', $v) != 1) {
$localname = $v;
}
if ($localname) {
dbg_error_log( 'POST', 'try to resolve local attendee %s', $localname);
$qry = new AwlQuery('SELECT fullname, email FROM usr WHERE user_no = (SELECT user_no FROM principal WHERE type_id = 1 AND user_no = (SELECT user_no FROM usr WHERE lower(username) = (text(:username)))) UNION SELECT fullname, email FROM usr WHERE user_no IN (SELECT user_no FROM principal WHERE principal_id IN (SELECT member_id FROM group_member WHERE group_id = (SELECT principal_id FROM principal WHERE type_id = 3 AND user_no = (SELECT user_no FROM usr WHERE lower(username) = (text(:username))))))', array(':username' => strtolower($localname)));
if ( $qry->Exec('POST',__LINE__,__FILE__) && $qry->rows() >= 1 ) {
dbg_error_log( 'POST', 'resolved local name %s to %d individual attendees', $localname, $qry->rows());
while ($row = $qry->Fetch()) {
dbg_error_log( 'POST', 'adding individual attendee %s <%s>', $row->fullname, $row->email);
$new_attendees[] = new vProperty("ATTENDEE:mailto:" . $row->email);
}
}
} else {
$new_attendees[] = clone($attendee);
}
}
$attendees = $new_attendees;
}
foreach( $attendees AS $k => $attendee ) { foreach( $attendees AS $k => $attendee ) {
$attendee_email = preg_replace( '/^mailto:/', '', $attendee->Value() ); $attendee_email = preg_replace( '/^mailto:/', '', $attendee->Value() );
dbg_error_log( "POST", "Calculating free/busy for %s", $attendee_email ); dbg_error_log( "POST", "Calculating free/busy for %s", $attendee_email );

View File

@ -510,6 +510,52 @@ function do_scheduling_requests( vCalendar $resource, $create, $old_data = null
return do_scheduling_reply($resource,$organizer); return do_scheduling_reply($resource,$organizer);
} }
if ($c->enable_attendee_group_resolution) {
$mail_domain = preg_replace( '/^.*@/i', '', $c->admin_email );
$attendees = $resource->GetAttendees();
$new_attendees = array();
foreach( $attendees AS $attendee ) {
$v = $attendee->Value();
unset($localname);
if ($v == "invalid:nomail") {
$localname = $attendee->GetParameterValue("CN");
} else if ((preg_match('/^@/', $v) == 1) || (preg_match('/mailto:@/',$v) == 1)) {
$localname = preg_replace('/^.*@/', '', $v);
} else if (preg_match('/@/', $v) != 1) {
$localname = $v;
} else if (preg_match('/@'.$mail_domain.'/', $v) == 1) {
$localname = preg_replace('/@.*$/', '', $v);
$localname = preg_replace('/^mailto:/', '', $localname);
}
if ($localname) {
dbg_error_log( 'PUT', 'try to resolve local attendee %s', $localname);
$qry = new AwlQuery('SELECT fullname, email FROM usr WHERE user_no = (SELECT user_no FROM principal WHERE type_id = 1 AND user_no = (SELECT user_no FROM usr WHERE lower(username) = (text(:username)))) UNION SELECT fullname, email FROM usr WHERE user_no IN (SELECT user_no FROM principal WHERE principal_id IN (SELECT member_id FROM group_member WHERE group_id = (SELECT principal_id FROM principal WHERE type_id = 3 AND user_no = (SELECT user_no FROM usr WHERE lower(username) = (text(:username))))))', array(':username' => strtolower($localname)));
if ( $qry->Exec('PUT',__LINE__,__FILE__) && $qry->rows() >= 1 ) {
dbg_error_log( 'PUT', 'resolved local name %s to %d individual attendees', $localname, $qry->rows());
while ($row = $qry->Fetch()) {
if ($row->email == $request->principal->email()) continue;
dbg_error_log( 'PUT', 'adding individual attendee %s <%s>', $row->fullname, $row->email);
$a = clone($attendee);
$a->SetParameterValue("CN", $row->fullname);
$a->SetParameterValue("PARTSTAT", "NEEDS-ACTION");
$a->Value("mailto:" . $row->email);
$new_attendees[] = $a;
}
} else {
$new_attendees[] = clone($attendee);
}
} else {
$new_attendees[] = clone($attendee);
}
}
$events = $resource->GetComponents("VEVENT");
$event = $events[0];
$event->SetProperties($new_attendees,'ATTENDEE');
// this is just to reset the private attribute "attendees" in the $resource object
$resource->UpdateAttendeeStatus("this-is-nonsense", new vProperty("ATTENDEE:dummy"));
$attendees = $resource->GetAttendees();
}
// required because we set the schedule status on the original object (why clone() not works here?) // required because we set the schedule status on the original object (why clone() not works here?)
$orig_resource = new vCalendar($resource->Render(null, true)); $orig_resource = new vCalendar($resource->Render(null, true));