Skip to content

Commit acbd711

Browse files
committed
Optimise the error message
1 parent 0991c30 commit acbd711

3 files changed

Lines changed: 70 additions & 8 deletions

File tree

lib/solidpod.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export 'src/solid/utils/exceptions.dart'
8484
AccessForbiddenException,
8585
AccessFailedException,
8686
NotLoggedInException,
87+
RecipientNotReadyException,
8788
ResourceNotExistException,
8889
SecurityKeyNotAvailableException;
8990

lib/src/solid/send_notification.dart

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ import 'package:solidpod/src/solid/utils/misc.dart' show isUserLoggedIn;
6363
/// Convention: 0 = low, 1 = medium, 2 = high
6464
///
6565
/// Throws [NotLoggedInException] if the user is not authenticated.
66+
/// Throws [RecipientNotReadyException] if the recipient's WebID does not
67+
/// exist or their Pod lacks the notification folder for this app.
6668
6769
Future<void> sendNotification({
6870
required String recipientWebId,
@@ -81,6 +83,36 @@ Future<void> sendNotification({
8183
throw NotLoggedInException('Unable to retrieve sender WebID');
8284
}
8385

86+
// Pre-flight checks.
87+
88+
// 1. Verify the recipient's WebID exists (unauthenticated GET to the
89+
// public profile document).
90+
91+
final webIdStatus = await checkWebIdExists(recipientWebId);
92+
if (webIdStatus == ResourceStatus.notExist) {
93+
throw RecipientNotReadyException(
94+
'The recipient WebID does not exist: $recipientWebId. '
95+
'Please check the WebID is correct.',
96+
);
97+
}
98+
99+
// 2. Verify the recipient has initialised their Pod for this app.
100+
// checkPodInitialised performs an authenticated GET on the recipient's
101+
// shared directory — the same check used in the grant-permissions
102+
// workflow. If it returns false the recipient has never set up the app.
103+
104+
final podReady = await checkPodInitialised(recipientWebId);
105+
if (!podReady) {
106+
throw RecipientNotReadyException(
107+
'The recipient ($recipientWebId) has not set up this app on their '
108+
'Pod. They need to log in to the app first so that the required '
109+
'folder structure is created, before you can send notifications '
110+
'to them.',
111+
);
112+
}
113+
114+
// Build and send the notification.
115+
84116
final timestamp = DateTime.now().millisecondsSinceEpoch;
85117

86118
final notification = PodNotification(
@@ -101,17 +133,33 @@ Future<void> sendNotification({
101133

102134
final jsonContent = jsonEncode(notification.toJson());
103135

104-
// debugPrint('[sendNotification] Writing to: $fileUrl');
105-
106136
// POST the notification JSON to the recipient's notification container.
107137
// replaceIfExist: false triggers POST (instead of PUT), which only
108138
// requires Append access on the container — matching the public Append
109139
// ACL configured during POD initialisation.
140+
//
141+
// If the POST still fails (e.g. the notification folder was added in a
142+
// newer app version that the recipient has not yet run), convert the
143+
// error into a RecipientNotReadyException with actionable guidance.
110144

111-
await createResource(
112-
fileUrl,
113-
content: jsonContent,
114-
contentType: ResourceContentType.auto,
115-
replaceIfExist: false,
116-
);
145+
try {
146+
await createResource(
147+
fileUrl,
148+
content: jsonContent,
149+
contentType: ResourceContentType.auto,
150+
replaceIfExist: false,
151+
);
152+
} on Exception catch (e) {
153+
final errStr = e.toString();
154+
if (errStr.contains('403') || errStr.contains('Forbidden')) {
155+
throw RecipientNotReadyException(
156+
'The recipient ($recipientWebId) does not have a notification '
157+
'folder for this app. This typically happens when the recipient '
158+
'has not run the latest version of the app. They need to log in '
159+
'and update their app setup in their Pod before you can send '
160+
'notifications to them.',
161+
);
162+
}
163+
rethrow;
164+
}
117165
}

lib/src/solid/utils/exceptions.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,16 @@ class SecurityKeyNotAvailableException implements Exception {
7272
@override
7373
String toString() => 'SecurityKeyNotAvailableException: $message';
7474
}
75+
76+
/// Thrown when a notification cannot be delivered because the recipient's Pod
77+
/// is not ready — either their WebID does not exist, they have not set up the
78+
/// app, or their notification folder has not yet been created.
79+
80+
class RecipientNotReadyException implements Exception {
81+
final String message;
82+
83+
RecipientNotReadyException(this.message);
84+
85+
@override
86+
String toString() => 'RecipientNotReadyException: $message';
87+
}

0 commit comments

Comments
 (0)