Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/src/rbac/permissions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ abstract class Permissions {
'push_notification_device.create_owned';
static const String pushNotificationDeviceDeleteOwned =
'push_notification_device.delete_owned';
// Allows reading the user's own push notification devices.
static const String pushNotificationDeviceReadOwned =
'push_notification_device.read_owned';

// In-App Notification Permissions (User-owned)
/// Allows reading the user's own in-app notifications.
Expand Down
1 change: 1 addition & 0 deletions lib/src/rbac/role_permissions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ final Set<String> _appGuestUserPermissions = {
// notifications.
Permissions.pushNotificationDeviceCreateOwned,
Permissions.pushNotificationDeviceDeleteOwned,
Permissions.pushNotificationDeviceReadOwned,
// Allow all app users to manage their own in-app notifications.
Permissions.inAppNotificationReadOwned,
Permissions.inAppNotificationUpdateOwned,
Expand Down
7 changes: 7 additions & 0 deletions lib/src/registry/data_operation_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ class DataOperationRegistry {
sort: s,
pagination: p,
),
'push_notification_device': (c, uid, f, s, p) =>
c.read<DataRepository<PushNotificationDevice>>().readAll(
userId: uid,
filter: f,
sort: s,
pagination: p,
),
});

// --- Register Item Creators ---
Expand Down
13 changes: 10 additions & 3 deletions lib/src/registry/model_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,19 @@ final modelRegistry = <String, ModelConfig<dynamic>>{
fromJson: PushNotificationDevice.fromJson,
getId: (d) => d.id,
getOwnerId: (dynamic item) => (item as PushNotificationDevice).userId,
// Collection GET is allowed for a user to fetch their own notification devices.
// The generic route handler will automatically scope the query to the
// authenticated user's ID because `getOwnerId` is defined.
getCollectionPermission: const ModelActionPermission(
type: RequiredPermissionType.unsupported,
type: RequiredPermissionType.specificPermission,
permission: Permissions.pushNotificationDeviceReadOwned,
),
// Required by the ownership check middelware
// Item GET is allowed for a user to fetch a single one of their devices.
// The ownership check middleware will verify they own this specific item.
getItemPermission: const ModelActionPermission(
type: RequiredPermissionType.adminOnly,
type: RequiredPermissionType.specificPermission,
permission: Permissions.pushNotificationDeviceReadOwned,
requiresOwnershipCheck: true,
),
// POST is allowed for any authenticated user to register their own device.
// A custom check within the DataOperationRegistry's creator function will
Expand Down
6 changes: 6 additions & 0 deletions lib/src/services/database_seeding_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ class DatabaseSeedingService {
'unique': true,
'sparse': true,
},
{
// Optimizes fetching all devices for a specific user, which is
// needed for the device cleanup flow on the client.
'key': {'userId': 1},
'name': 'userId_index',
},
],
});
_log.info('Ensured indexes for "push_notification_devices".');
Expand Down
Loading