Merge pull request #1928 from pbiering/support-discussion-1926
Support discussion 1926
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 3.5.10.dev
|
## 3.5.10.dev
|
||||||
|
* Improve: logging of broken calendar items during PUT
|
||||||
|
* Add: logging of broken contact items during PUT
|
||||||
|
|
||||||
## 3.5.9
|
## 3.5.9
|
||||||
* Extend: [auth] add support for type http_remote_user
|
* Extend: [auth] add support for type http_remote_user
|
||||||
|
|||||||
@@ -93,9 +93,13 @@ def prepare(vobject_items: List[vobject.base.Component], path: str,
|
|||||||
logger.debug("Prepare item with UID '%s'", item.uid)
|
logger.debug("Prepare item with UID '%s'", item.uid)
|
||||||
try:
|
try:
|
||||||
item.prepare()
|
item.prepare()
|
||||||
except ValueError as e:
|
except (RuntimeError, ValueError, AttributeError) as e:
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, item._text)
|
if item._text is None:
|
||||||
|
content = vobject_item
|
||||||
|
else:
|
||||||
|
content = item._text
|
||||||
|
logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, content)
|
||||||
else:
|
else:
|
||||||
logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e)
|
logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e)
|
||||||
raise
|
raise
|
||||||
@@ -104,7 +108,19 @@ def prepare(vobject_items: List[vobject.base.Component], path: str,
|
|||||||
for vobject_item in vobject_items:
|
for vobject_item in vobject_items:
|
||||||
item = radicale_item.Item(collection_path=collection_path,
|
item = radicale_item.Item(collection_path=collection_path,
|
||||||
vobject_item=vobject_item)
|
vobject_item=vobject_item)
|
||||||
item.prepare()
|
logger.debug("Prepare item with UID '%s'", item.uid)
|
||||||
|
try:
|
||||||
|
item.prepare()
|
||||||
|
except (RuntimeError, ValueError, AttributeError) as e:
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
if item._text is None:
|
||||||
|
content = vobject_item
|
||||||
|
else:
|
||||||
|
content = item._text
|
||||||
|
logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, content)
|
||||||
|
else:
|
||||||
|
logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e)
|
||||||
|
raise
|
||||||
items.append(item)
|
items.append(item)
|
||||||
elif not write_whole_collection:
|
elif not write_whole_collection:
|
||||||
vobject_item, = vobject_items
|
vobject_item, = vobject_items
|
||||||
|
|||||||
@@ -354,7 +354,10 @@ def visit_time_ranges(vobject_item: vobject.base.Component, child_name: str,
|
|||||||
for child, is_recurrence, recurrences in get_children(
|
for child, is_recurrence, recurrences in get_children(
|
||||||
vobject_item.vevent_list):
|
vobject_item.vevent_list):
|
||||||
# TODO: check if there's a timezone
|
# TODO: check if there's a timezone
|
||||||
dtstart = child.dtstart.value
|
try:
|
||||||
|
dtstart = child.dtstart.value
|
||||||
|
except AttributeError:
|
||||||
|
raise AttributeError("missing DTSTART")
|
||||||
|
|
||||||
if child.rruleset:
|
if child.rruleset:
|
||||||
dtstarts, infinity = getrruleset(child, recurrences)
|
dtstarts, infinity = getrruleset(child, recurrences)
|
||||||
|
|||||||
16
radicale/tests/static/broken-vcards.vcf
Normal file
16
radicale/tests/static/broken-vcards.vcf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
UID:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example.com
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
END:VCARD
|
||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
UID:C68582D2-2E60-0001-C2C0-000000000001.vcf
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example1.com
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000001.vcf
|
||||||
|
END:VCARD
|
||||||
16
radicale/tests/static/broken-vcards2-no_uid.vcf
Normal file
16
radicale/tests/static/broken-vcards2-no_uid.vcf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
UID:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example.com
|
||||||
|
FN:Test Example
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
END:VCARD
|
||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example1.com
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000001.vcf
|
||||||
|
END:VCARD
|
||||||
17
radicale/tests/static/broken-vcards2.vcf
Normal file
17
radicale/tests/static/broken-vcards2.vcf
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
UID:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example.com
|
||||||
|
FN:Test Example
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000000.vcf
|
||||||
|
END:VCARD
|
||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
PRODID:-//Inverse inc.//SOGo Connector 1.0//EN
|
||||||
|
UID:C68582D2-2E60-0001-C2C0-000000000001.vcf
|
||||||
|
X-MOZILLA-HTML:FALSE
|
||||||
|
EMAIL;TYPE=work:test-misses-N-or-FN@example1.com
|
||||||
|
X-RADICALE-NAME:C68582D2-2E60-0001-C2C0-000000000001.vcf
|
||||||
|
END:VCARD
|
||||||
25
radicale/tests/static/broken-vevents.ics
Normal file
25
radicale/tests/static/broken-vevents.ics
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
PRODID:-//Radicale//NONSGML Radicale Server//EN
|
||||||
|
VERSION:2.0
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20160725T060147Z
|
||||||
|
LAST-MODIFIED:20160727T193435Z
|
||||||
|
DTSTAMP:20160727T193435Z
|
||||||
|
UID:040000008200E00074C5B7101A82E00800000000
|
||||||
|
SUMMARY:Good ICS
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
X-MOZ-LASTACK:20160727T193435Z
|
||||||
|
DTSTART;TZID=Europe/Budapest:20160727T170000
|
||||||
|
DTEND;TZID=Europe/Budapest:20160727T223000
|
||||||
|
CLASS:PUBLIC
|
||||||
|
X-LIC-ERROR:No value for LOCATION property. Removing entire property:
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20160725T060147Z
|
||||||
|
LAST-MODIFIED:20160727T193435Z
|
||||||
|
DTSTAMP:20160727T193435Z
|
||||||
|
UID:040000008200E00074C5B7101A82E00800000001
|
||||||
|
CLASS:PUBLIC
|
||||||
|
X-LIC-ERROR:No value for LOCATION property. Removing entire property:
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
@@ -142,6 +142,20 @@ permissions: RrWw""")
|
|||||||
assert "Event" in answer
|
assert "Event" in answer
|
||||||
assert "UID:event" in answer
|
assert "UID:event" in answer
|
||||||
|
|
||||||
|
def test_add_event_broken(self) -> None:
|
||||||
|
"""Add a broken event."""
|
||||||
|
self.mkcalendar("/calendar.ics/")
|
||||||
|
event = get_file_content("broken-vevent.ics")
|
||||||
|
path = "/calendar.ics/broken-vevent.ics"
|
||||||
|
self.put(path, event, check=400)
|
||||||
|
|
||||||
|
def test_add_events_broken2(self) -> None:
|
||||||
|
"""Add a broken event (2nd one is broken)."""
|
||||||
|
self.mkcalendar("/calendar.ics/")
|
||||||
|
event = get_file_content("broken-vevents.ics")
|
||||||
|
path = "/calendar.ics/"
|
||||||
|
self.put(path, event, check=400)
|
||||||
|
|
||||||
def test_add_event_without_uid(self) -> None:
|
def test_add_event_without_uid(self) -> None:
|
||||||
"""Add an event without UID."""
|
"""Add an event without UID."""
|
||||||
self.mkcalendar("/calendar.ics/")
|
self.mkcalendar("/calendar.ics/")
|
||||||
@@ -201,6 +215,34 @@ permissions: RrWw""")
|
|||||||
_, answer = self.get(path)
|
_, answer = self.get(path)
|
||||||
assert "UID:contact1" in answer
|
assert "UID:contact1" in answer
|
||||||
|
|
||||||
|
def test_add_contact_broken(self) -> None:
|
||||||
|
"""Add a broken contact."""
|
||||||
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
contact = get_file_content("broken-vcard.vcf")
|
||||||
|
path = "/contacts.vcf/broken-vcards.vcf"
|
||||||
|
self.put(path, contact, check=400)
|
||||||
|
|
||||||
|
def test_add_contacts_broken(self) -> None:
|
||||||
|
"""Add broken contacts."""
|
||||||
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
contact = get_file_content("broken-vcards.vcf")
|
||||||
|
path = "/contacts.vcf/"
|
||||||
|
self.put(path, contact, check=400)
|
||||||
|
|
||||||
|
def test_add_contacts_broken2(self) -> None:
|
||||||
|
"""Add broken contacts (only 2nd one is broken)."""
|
||||||
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
contact = get_file_content("broken-vcards2.vcf")
|
||||||
|
path = "/contacts.vcf/"
|
||||||
|
self.put(path, contact, check=400)
|
||||||
|
|
||||||
|
def test_add_contacts_broken2_no_uid(self) -> None:
|
||||||
|
"""Add broken contacts (only 2nd one is broken and has no UID)."""
|
||||||
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
contact = get_file_content("broken-vcards2-no_uid.vcf")
|
||||||
|
path = "/contacts.vcf/"
|
||||||
|
self.put(path, contact, check=400)
|
||||||
|
|
||||||
def test_add_contact_photo_with_data_uri(self) -> None:
|
def test_add_contact_photo_with_data_uri(self) -> None:
|
||||||
"""Test workaround for broken PHOTO data from InfCloud"""
|
"""Test workaround for broken PHOTO data from InfCloud"""
|
||||||
self.create_addressbook("/contacts.vcf/")
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
|||||||
Reference in New Issue
Block a user