Commit 83dab17f authored by Ricki Hirner's avatar Ricki Hirner

Events: use ACCESS_CONFIDENTIAL

* export ACCESS_CONFIDENTIAL as CLASS:CONFIDENTIAL
* import CLASS:CONFIDENTIAL as ACCESS_CONFIDENTIAL and retain it as unknown property
* export ACCESS_DEFAULT as (no CLASS) when no CLASS is retained
* export ACCESS_DEFAULT as the retained CLASS value in case there is one
parent d04d1cc2
Pipeline #12976348 passed with stage
in 2 minutes and 7 seconds
......@@ -30,6 +30,7 @@ import net.fortuna.ical4j.model.TimeZone;
import net.fortuna.ical4j.model.component.VAlarm;
import net.fortuna.ical4j.model.parameter.Value;
import net.fortuna.ical4j.model.property.Attendee;
import net.fortuna.ical4j.model.property.Clazz;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.DtStart;
import net.fortuna.ical4j.model.property.Duration;
......@@ -108,7 +109,7 @@ public class AndroidEventTest extends InstrumentationTestCase {
event.setDtEnd(new DtEnd("20150501T130000", tzVienna));
event.setOrganizer(new Organizer(new URI("mailto:organizer@example.com")));
event.setRRule(new RRule("FREQ=DAILY;COUNT=10"));
event.setForPublic(false);
event.setClassification(Clazz.PRIVATE);
event.setStatus(Status.VEVENT_CONFIRMED);
event.setColor(EventColor.aliceblue);
assertFalse(event.isAllDay());
......@@ -153,7 +154,7 @@ public class AndroidEventTest extends InstrumentationTestCase {
assertFalse(event2.isAllDay());
assertEquals(event.getOrganizer(), event2.getOrganizer());
assertEquals(event.getRRule(), event2.getRRule());
assertEquals(event.getForPublic(), event2.getForPublic());
assertEquals(event.getClassification(), event2.getClassification());
assertEquals(event.getStatus(), event2.getStatus());
if (Build.VERSION.SDK_INT >= 23)
......@@ -313,6 +314,63 @@ public class AndroidEventTest extends InstrumentationTestCase {
assertTrue(event2.isAllDay());
}
public void testClassificationConfidential() throws Exception {
Event event = new Event();
event.setSummary("Confidential event");
event.setDtStart(new DtStart(new Date("20150501")));
event.setDtEnd(new DtEnd(new Date("20150502")));
event.setClassification(Clazz.CONFIDENTIAL);
Uri uri = new TestEvent(calendar, event).add();
assertNotNull("Couldn't add event", uri);
long id = ContentUris.parseId(uri);
// now, the calendar app changes to ACCESS_DEFAULT
ContentValues values = new ContentValues(1);
values.put(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_DEFAULT);
calendar.getProvider().update(calendar.syncAdapterURI(ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id)),
values, null, null);
// read again and verify result
@Cleanup("delete") TestEvent testEvent = new TestEvent(calendar, id);
Event event2 = testEvent.getEvent();
// CONFIDENTIAL has been retained
assertTrue(event.getUnknownProperties().contains(Clazz.CONFIDENTIAL));
// should still be CONFIDENTIAL
assertEquals(event.getClassification(), event2.getClassification());
// now, the calendar app changes to ACCESS_PRIVATE
values.put(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_PRIVATE);
calendar.getProvider().update(calendar.syncAdapterURI(ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id)),
values, null, null);
// read again and verify result
TestEvent testEventPrivate = new TestEvent(calendar, id);
Event eventPrivate = testEventPrivate.getEvent();
// should be PRIVATE
assertEquals(Clazz.PRIVATE, eventPrivate.getClassification());
// the retained value is not used in this case
assertFalse(eventPrivate.getUnknownProperties().contains(Clazz.CONFIDENTIAL));
}
public void testClassificationPrivate() throws Exception {
Event event = new Event();
event.setSummary("Private event");
event.setDtStart(new DtStart(new Date("20150501")));
event.setDtEnd(new DtEnd(new Date("20150502")));
event.setClassification(Clazz.PRIVATE);
Uri uri = new TestEvent(calendar, event).add();
assertNotNull("Couldn't add event", uri);
long id = ContentUris.parseId(uri);
// read again and verify result
@Cleanup("delete") TestEvent testEvent = new TestEvent(calendar, id);
Event event2 = testEvent.getEvent();
// PRIVATE has not been retained
assertFalse(event.getUnknownProperties().contains(Clazz.PRIVATE));
// should still be PRIVATE
assertEquals(Clazz.PRIVATE, event2.getClassification());
}
public void testNoOrganizerWithoutAttendees() throws ParseException, URISyntaxException, CalendarStorageException, FileNotFoundException {
Event event = new Event();
event.setSummary("Not a group-scheduled event");
......
......@@ -101,6 +101,8 @@ abstract class AndroidEvent(
}
populateExceptions()
useRetainedClassification()
/* remove ORGANIZER from all components if there are no attendees
(i.e. this is not a group-scheduled calendar entity) */
if (event.attendees.isEmpty()) {
......@@ -194,11 +196,10 @@ abstract class AndroidEvent(
}
// status
event.status = when (row.getAsInteger(Events.STATUS)) {
Events.STATUS_CONFIRMED -> Status.VEVENT_CONFIRMED
Events.STATUS_TENTATIVE -> Status.VEVENT_TENTATIVE
Events.STATUS_CANCELED -> Status.VEVENT_CANCELLED
else -> null
when (row.getAsInteger(Events.STATUS)) {
Events.STATUS_CONFIRMED -> event.status = Status.VEVENT_CONFIRMED
Events.STATUS_TENTATIVE -> event.status = Status.VEVENT_TENTATIVE
Events.STATUS_CANCELED -> event.status = Status.VEVENT_CANCELLED
}
// availability
......@@ -213,10 +214,10 @@ abstract class AndroidEvent(
}
// classification
event.forPublic = when (row.getAsInteger(Events.ACCESS_LEVEL)) {
Events.ACCESS_PUBLIC -> true
Events.ACCESS_PRIVATE -> false
else -> null
when (row.getAsInteger(Events.ACCESS_LEVEL)) {
Events.ACCESS_PUBLIC -> event.classification = Clazz.PUBLIC
Events.ACCESS_PRIVATE -> event.classification = Clazz.PRIVATE
Events.ACCESS_CONFIDENTIAL -> event.classification = Clazz.CONFIDENTIAL
}
// exceptions from recurring events
......@@ -350,6 +351,16 @@ abstract class AndroidEvent(
}
}
private fun retainClassification() {
/* retain classification other than PUBLIC and PRIVATE as unknown property so
that it can be reused when "server default" is selected */
val event = requireNotNull(event)
event.classification?.let {
if (it != Clazz.PUBLIC && it != Clazz.PRIVATE)
event.unknownProperties += it
}
}
@Throws(CalendarStorageException::class)
fun add(): Uri {
......@@ -377,6 +388,7 @@ abstract class AndroidEvent(
event.attendees.forEach { insertAttendee(batch, idxEvent, it) }
// add unknown properties
retainClassification()
event.unknownProperties.forEach { insertUnknownProperty(batch, idxEvent, it) }
// add exceptions
......@@ -567,8 +579,10 @@ abstract class AndroidEvent(
builder.withValue(Events.AVAILABILITY, if (event.opaque) Events.AVAILABILITY_BUSY else Events.AVAILABILITY_FREE)
event.forPublic?.let { forPublic ->
builder.withValue(Events.ACCESS_LEVEL, if (forPublic) Events.ACCESS_PUBLIC else Events.ACCESS_PRIVATE)
when (event.classification) {
Clazz.PUBLIC -> builder.withValue(Events.ACCESS_LEVEL, Events.ACCESS_PUBLIC)
Clazz.PRIVATE -> builder.withValue(Events.ACCESS_LEVEL, Events.ACCESS_PRIVATE)
Clazz.CONFIDENTIAL -> builder.withValue(Events.ACCESS_LEVEL, Events.ACCESS_CONFIDENTIAL)
}
Constants.log.log(Level.FINE, "Built event object", builder.build())
......@@ -673,6 +687,24 @@ abstract class AndroidEvent(
}
}
private fun useRetainedClassification() {
val event = requireNotNull(event)
var retainedClazz: Clazz? = null
val it = event.unknownProperties.iterator()
while (it.hasNext()) {
val prop = it.next()
if (prop is Clazz) {
retainedClazz = prop
it.remove()
}
}
if (event.classification == null)
// no classification, use retained one if possible
event.classification = retainedClazz
}
protected fun eventsSyncURI() = calendar.syncAdapterURI(Events.CONTENT_URI)
......
......@@ -43,7 +43,7 @@ class Event: iCalendar() {
val exceptions = LinkedList<Event>()
var forPublic: Boolean? = null
var classification: Clazz? = null
var status: Status? = null
var opaque = true
......@@ -172,7 +172,7 @@ class Event: iCalendar() {
is RDate -> e.rDates += prop
is ExRule -> e.exRule = prop
is ExDate -> e.exDates += prop
is Clazz -> e.forPublic = prop == Clazz.PUBLIC
is Clazz -> e.classification = prop
is Status -> e.status = prop
is Transp -> e.opaque = prop == Transp.OPAQUE
is Organizer -> e.organizer = prop
......@@ -252,6 +252,7 @@ class Event: iCalendar() {
exRule?.let { props += it }
props.addAll(exDates)
classification?.let { props += it }
status?.let { props += it }
if (!opaque)
props += Transp.TRANSPARENT
......@@ -259,10 +260,9 @@ class Event: iCalendar() {
organizer?.let { props += it }
props.addAll(attendees)
forPublic?.let { props += if (it) Clazz.PUBLIC else Clazz.PRIVATE }
props.addAll(unknownProperties)
lastModified?.let { props += it }
props.addAll(unknownProperties)
event.alarms.addAll(alarms)
return event
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment