mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-06-10 21:09:50 +00:00
fix(calendar): filter by matching property values
Added test for calendar-query DAV request
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user