refactor(ios): share EventKit auth gating

This commit is contained in:
Peter Steinberger
2026-02-15 20:24:06 +00:00
parent 71009ab1b6
commit b30ed6ca4c
3 changed files with 38 additions and 68 deletions

View File

@@ -6,7 +6,7 @@ final class CalendarService: CalendarServicing {
func events(params: OpenClawCalendarEventsParams) async throws -> OpenClawCalendarEventsPayload {
let store = EKEventStore()
let status = EKEventStore.authorizationStatus(for: .event)
let authorized = await Self.ensureAuthorization(store: store, status: status)
let authorized = EventKitAuthorization.allowsRead(status: status)
guard authorized else {
throw NSError(domain: "Calendar", code: 1, userInfo: [
NSLocalizedDescriptionKey: "CALENDAR_PERMISSION_REQUIRED: grant Calendar permission",
@@ -39,7 +39,7 @@ final class CalendarService: CalendarServicing {
func add(params: OpenClawCalendarAddParams) async throws -> OpenClawCalendarAddPayload {
let store = EKEventStore()
let status = EKEventStore.authorizationStatus(for: .event)
let authorized = await Self.ensureWriteAuthorization(store: store, status: status)
let authorized = EventKitAuthorization.allowsWrite(status: status)
guard authorized else {
throw NSError(domain: "Calendar", code: 2, userInfo: [
NSLocalizedDescriptionKey: "CALENDAR_PERMISSION_REQUIRED: grant Calendar permission",
@@ -95,38 +95,6 @@ final class CalendarService: CalendarServicing {
return OpenClawCalendarAddPayload(event: payload)
}
private static func ensureAuthorization(store: EKEventStore, status: EKAuthorizationStatus) async -> Bool {
switch status {
case .authorized:
return true
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
case .fullAccess:
return true
case .writeOnly:
return false
@unknown default:
return false
}
}
private static func ensureWriteAuthorization(store: EKEventStore, status: EKAuthorizationStatus) async -> Bool {
switch status {
case .authorized, .fullAccess, .writeOnly:
return true
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
@unknown default:
return false
}
}
private static func resolveCalendar(
store: EKEventStore,
calendarId: String?,

View File

@@ -0,0 +1,34 @@
import EventKit
enum EventKitAuthorization {
static func allowsRead(status: EKAuthorizationStatus) -> Bool {
switch status {
case .authorized, .fullAccess:
return true
case .writeOnly:
return false
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
@unknown default:
return false
}
}
static func allowsWrite(status: EKAuthorizationStatus) -> Bool {
switch status {
case .authorized, .fullAccess, .writeOnly:
return true
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
@unknown default:
return false
}
}
}

View File

@@ -6,7 +6,7 @@ final class RemindersService: RemindersServicing {
func list(params: OpenClawRemindersListParams) async throws -> OpenClawRemindersListPayload {
let store = EKEventStore()
let status = EKEventStore.authorizationStatus(for: .reminder)
let authorized = await Self.ensureAuthorization(store: store, status: status)
let authorized = EventKitAuthorization.allowsRead(status: status)
guard authorized else {
throw NSError(domain: "Reminders", code: 1, userInfo: [
NSLocalizedDescriptionKey: "REMINDERS_PERMISSION_REQUIRED: grant Reminders permission",
@@ -50,7 +50,7 @@ final class RemindersService: RemindersServicing {
func add(params: OpenClawRemindersAddParams) async throws -> OpenClawRemindersAddPayload {
let store = EKEventStore()
let status = EKEventStore.authorizationStatus(for: .reminder)
let authorized = await Self.ensureWriteAuthorization(store: store, status: status)
let authorized = EventKitAuthorization.allowsWrite(status: status)
guard authorized else {
throw NSError(domain: "Reminders", code: 2, userInfo: [
NSLocalizedDescriptionKey: "REMINDERS_PERMISSION_REQUIRED: grant Reminders permission",
@@ -100,38 +100,6 @@ final class RemindersService: RemindersServicing {
return OpenClawRemindersAddPayload(reminder: payload)
}
private static func ensureAuthorization(store: EKEventStore, status: EKAuthorizationStatus) async -> Bool {
switch status {
case .authorized:
return true
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
case .fullAccess:
return true
case .writeOnly:
return false
@unknown default:
return false
}
}
private static func ensureWriteAuthorization(store: EKEventStore, status: EKAuthorizationStatus) async -> Bool {
switch status {
case .authorized, .fullAccess, .writeOnly:
return true
case .notDetermined:
// Dont prompt during node.invoke; prompts block the invoke and lead to timeouts.
return false
case .restricted, .denied:
return false
@unknown default:
return false
}
}
private static func resolveList(
store: EKEventStore,
listId: String?,