fix(calendar): filter by matching property values

Added test for calendar-query DAV request
This commit is contained in:
Francis Lachapelle
2022-05-24 17:29:56 -04:00
parent dec49c2154
commit 5452cd7396
5 changed files with 94 additions and 13 deletions
@@ -793,7 +793,7 @@ static Class iCalEventK = nil;
if ([title length])
[baseWhere
addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'",
addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '*%@*'",
[title asSafeSQLLikeString]]];
if (component)
@@ -1576,14 +1576,14 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
{
if ([filters isEqualToString:@"title_Category_Location"] || [filters isEqualToString:@"entireContent"])
{
[baseWhere addObject: [NSString stringWithFormat: @"(c_title isCaseInsensitiveLike: '%%%@%%' OR c_category isCaseInsensitiveLike: '%%%@%%' OR c_location isCaseInsensitiveLike: '%%%@%%')",
[baseWhere addObject: [NSString stringWithFormat: @"(c_title isCaseInsensitiveLike: '*%@*' OR c_category isCaseInsensitiveLike: '*%@*' OR c_location isCaseInsensitiveLike: '*%@*')",
[title asSafeSQLLikeString],
[title asSafeSQLLikeString],
[title asSafeSQLLikeString]]];
}
}
else
[baseWhere addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '%%%@%%'",
[baseWhere addObject: [NSString stringWithFormat: @"c_title isCaseInsensitiveLike: '*%@*'",
[title asSafeSQLLikeString]]];
}
@@ -1954,7 +1954,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
filterString = [NSString stringWithFormat: @"(%@ = '')", key];
else
filterString
= [NSString stringWithFormat: @"(%@ like '%%%@%%')", key, value];
= [NSString stringWithFormat: @"(%@ like '*%@*')", key, value];
}
else
filterString = [NSString stringWithFormat: @"(%@ != '')", key];
@@ -2169,6 +2169,8 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
return davSQLFieldsTable;
}
// CALDAV:calendar-query REPORT
// https://datatracker.ietf.org/doc/html/rfc4791#section-7.8
- (id) davCalendarQuery: (id) queryContext
{
WOResponse *r;
@@ -1731,10 +1731,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
ex = [self exceptionWithHTTPStatus: 404 // Not Found
reason: @"user does not participate in this calendar event"];
}
else
ex = [self exceptionWithHTTPStatus: 500 // Server Error
reason: @"unable to parse event record"];
else
ex = [self exceptionWithHTTPStatus: 500 // Server Error
reason: @"unable to parse event record"];
return ex;
}
+14
View File
@@ -11,6 +11,7 @@ import {
propfind,
calendarMultiGet,
calendarQuery,
createCalendarObject,
makeCalendar,
@@ -408,6 +409,19 @@ class WebDAV {
})
}
calendarQuery(resource, filters) {
return calendarQuery({
url: this.serverUrl + resource,
headers: this.headers,
depth: '1',
props: [
{ name: 'getetag', namespace: DAVNamespace.DAV },
{ name: 'calendar-data', namespace: DAVNamespace.CALDAV },
],
filters,
})
}
calendarMultiGet(resource, filename) {
return calendarMultiGet({
url: this.serverUrl + resource,
+61
View File
@@ -1,8 +1,10 @@
import config from '../lib/config'
import WebDAV from '../lib/WebDAV'
import TestUtility from '../lib/utilities'
describe('read and set calendar properties', function() {
const webdav = new WebDAV(config.username, config.password)
const utility = new TestUtility(webdav)
const resource = `/SOGo/dav/${config.username}/Calendar/test-dav-properties/`
beforeEach(async function() {
@@ -56,6 +58,65 @@ describe('read and set calendar properties', function() {
expect(results[0].status)
.withContext(`Setting transparency to ${newValueNode} is successful`)
.toBe(207)
})
it("calendar-query", async function() {
const filename = `new.ics`
const event = `BEGIN:VCALENDAR
PRODID:-//Inverse//Event Generator//EN
VERSION:2.0
BEGIN:VEVENT
SEQUENCE:0
TRANSP:OPAQUE
UID:1234567890
SUMMARY:Visit to the museum of fine arts
DTSTART:20090805T100000Z
DTEND:20090805T140000Z
CLASS:PUBLIC
DESCRIPTION:description
LOCATION:location
DTSTAMP:20090805T100000Z
END:VEVENT
END:VCALENDAR`
let response = await webdav.createCalendarObject(resource, filename, event)
expect(response.status).toBe(201)
response = await webdav.calendarQuery(
resource,
[
{
type: 'comp-filter',
attributes: { name: 'VCALENDAR' },
children: [
{
type: 'comp-filter',
attributes: { name: 'VEVENT' },
children: [
{
type: 'prop-filter',
attributes: { name: 'TITLE' },
children: [
{
type: 'text-match',
value: 'museum'
}
]
}
]
}
]
}
]
)
expect(response.length)
.withContext(`Number of results from calendar-query`)
.toBe(1)
expect(response[0].status)
.withContext(`HTTP status code of calendar-query`)
.toEqual(207)
expect(utility.componentsAreEqual(response[0].props.calendarData, event))
.withContext(`Returned vCalendar matches ${filename}`)
.toBe(true)
})
})
+9 -5
View File
@@ -88,6 +88,15 @@ describe('Apple iCal', function() {
.toContain(`/SOGo/dav/${config.username}/`)
}
beforeEach(async function() {
await _setMemberSet(config.username, [], 'read')
await _setMemberSet(config.username, [], 'write')
await _setMemberSet(config.subscriber_username, [], 'read')
await _setMemberSet(config.subscriber_username, [], 'write')
await _setMemberSet(config.superuser, [], 'read')
await _setMemberSet(config.superuser, [], 'write')
})
// iCalTest
it(`principal-collection-set: 'DAV' header must be returned with iCal 4`, async function() {
@@ -127,11 +136,6 @@ describe('Apple iCal', function() {
it(`calendar-proxy as used from iCal`, async function() {
let membership, perm, users, proxyFor
await _setMemberSet(config.username, [], 'read')
await _setMemberSet(config.username, [], 'write')
await _setMemberSet(config.subscriber_username, [], 'read')
await _setMemberSet(config.subscriber_username, [], 'write')
membership = await _getMembership(config.username)
expect(membership.length)
.toBe(0)