diff --git a/android/src/main/kotlin/sncf/connect/tech/eventide/CalendarImplem.kt b/android/src/main/kotlin/sncf/connect/tech/eventide/CalendarImplem.kt index f700746..fe5839f 100644 --- a/android/src/main/kotlin/sncf/connect/tech/eventide/CalendarImplem.kt +++ b/android/src/main/kotlin/sncf/connect/tech/eventide/CalendarImplem.kt @@ -188,17 +188,34 @@ class CalendarImplem( val selection = CalendarContract.Calendars._ID + " = ?" val selectionArgs = arrayOf(calendarId) - val deleted = contentResolver.delete(calendarContentUri, selection, selectionArgs) - if (deleted > 0) { - callback(Result.success(Unit)) + if (isCalendarWritable(calendarId)) { + val deleted = contentResolver.delete(calendarContentUri, selection, selectionArgs) + if (deleted > 0) { + callback(Result.success(Unit)) + } else { + callback( + Result.failure( + FlutterError( + code = "NOT_FOUND", + message = "Failed to delete calendar" + ) + ) + ) + } } else { - callback(Result.failure( - FlutterError( - code = "NOT_FOUND", - message = "Failed to delete calendar" + callback( + Result.failure( + FlutterError( + code = "NOT_EDITABLE", + message = "Calendar is not writable" + ) ) - )) + ) } + + } catch (e: FlutterError) { + callback(Result.failure(e)) + } catch (e: Exception) { callback(Result.failure( FlutterError( @@ -234,6 +251,8 @@ class CalendarImplem( if (granted) { CoroutineScope(Dispatchers.IO).launch { try { + // TODO: check if calendar is writable + val eventValues = ContentValues().apply { put(CalendarContract.Events.CALENDAR_ID, calendarId) put(CalendarContract.Events.TITLE, title) @@ -397,6 +416,7 @@ class CalendarImplem( if (granted) { CoroutineScope(Dispatchers.IO).launch { try { + // TODO: check if calendar is writable val selection = CalendarContract.Events._ID + " = ?" val selectionArgs = arrayOf(eventId) @@ -507,6 +527,34 @@ class CalendarImplem( } } + private fun isCalendarWritable( + calendarId: String, + ): Boolean { + val projection = arrayOf( + CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL + ) + val selection = CalendarContract.Calendars._ID + " = ?" + val selectionArgs = arrayOf(calendarId) + + val cursor = contentResolver.query(calendarContentUri, projection, selection, selectionArgs, null) + cursor?.use { + if (it.moveToNext()) { + val accessLevel = it.getInt(it.getColumnIndexOrThrow(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL)) + return accessLevel >= CalendarContract.Calendars.CAL_ACCESS_CONTRIBUTOR + } else { + throw FlutterError( + code = "NOT_FOUND", + message = "Failed to retrieve calendar" + ) + } + } + + throw FlutterError( + code = "GENERIC_ERROR", + message = "An error occurred" + ) + } + private fun retrieveEvent( eventId: String, callback: (Result) -> Unit diff --git a/android/src/test/kotlin/sncf/connect/tech/eventide/CalendarImplemTest.kt b/android/src/test/kotlin/sncf/connect/tech/eventide/CalendarImplemTest.kt index 8c992db..cbdecb3 100644 --- a/android/src/test/kotlin/sncf/connect/tech/eventide/CalendarImplemTest.kt +++ b/android/src/test/kotlin/sncf/connect/tech/eventide/CalendarImplemTest.kt @@ -316,10 +316,14 @@ class CalendarImplemTest { } @Test - fun deleteCalendar_withGrantedPermission_deletesCalendarSuccessfully() = runTest { + fun deleteCalendar_withGrantedPermission_andWritableCalendar_deletesCalendarSuccessfully() = runTest { every { permissionHandler.requestWritePermission(any()) } answers { firstArg<(Boolean) -> Unit>().invoke(true) } + val cursor = mockk(relaxed = true) + every { contentResolver.query(calendarContentUri, any(), any(), any(), any()) } returns cursor + every { cursor.moveToNext() } returns true + every { cursor.getInt(any()) } returns CalendarContract.Calendars.CAL_ACCESS_OWNER every { contentResolver.delete(calendarContentUri, any(), any()) } returns 1 var result: Result? = null