-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/integrate with notification service provider #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
fulleni
merged 64 commits into
main
from
feat/integrate-with-notification-service-provider
Nov 8, 2025
Merged
Changes from 56 commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
4755f4e
build(deps): update core dependency to latest commit
fulleni 62b4377
feat(notifications): add environment variables for push notifications
fulleni a0df8f5
feat(database): add isBreaking field to existing Headline documents
fulleni 35490a5
feat(database): add migration to introduce isBreaking field in headlines
fulleni 04c2df5
feat(core): add IPushNotificationClient interface
fulleni 62355f5
feat(notifications): add Firebase Cloud Messaging client implementation
fulleni 76b6065
feat(push-notification): implement OneSignal push notification client
fulleni 79e9beb
feat(push-notification): implement push notification service
fulleni d771d16
feat(rbac): add permission for sending breaking news notifications
fulleni 7bccf20
feat(rbac): add push notification permission for dashboard publishers
fulleni e6c7701
feat(config): add environment variables for Firebase and OneSignal
fulleni 2f69a26
feat(routes): integrate push notification service
fulleni 2d2de04
feat(push-notification): implement push notification service and infr…
fulleni ec916f7
feat(headline): add breaking news notification
fulleni f928619
perf(database): optimize query for updating headlines with isBreaking…
fulleni f59192f
feat(push-notification): implement token providers for Firebase and O…
fulleni 83b05c6
fix(config): correct environment variable name for OneSignal API key
fulleni 13bfac8
feat(DataOperationRegistry): enhance breaking news notification process
fulleni 4331d5e
feat(limit_service): add notification subscription limits
fulleni bbdc33d
feat(database): add indexes for push notification collections
fulleni ef8d582
feat(push-notification): add bulk notification send function
fulleni c1a0d71
feat(firebase_push_notification_client): implement bulk messaging wit…
fulleni 0f81647
refactor(notifications): implement bulk sending for OneSignal client
fulleni 87fdb79
refactor(push-notification): optimize breaking news notification deli…
fulleni b5dcc80
docs(README): add detailed description of notification features
fulleni 28d9b52
style: format
fulleni 957edd9
refactor(user): improve notification subscription limit logic
fulleni 3e87476
refactor(push-notification): remove unused user repository dependency
fulleni 1566650
refactor(lib): remove unnecessary null check for pushConfig
fulleni a182a17
fix(database): add missing notificationSubscriptions field to user seed
fulleni 7328e4b
fix(auth_service): add notificationSubscriptions to create method
fulleni 3baf1e8
feat(rbac): add user-owned push notification device permissions
fulleni f34f46e
feat(push_notification): implement device registration and deletion
fulleni 133e4d5
build(deps): update core dependency
fulleni 5cb3e61
feat(database): add push notification config to remote config
fulleni e16d63c
refactor(config): correctly configure push notification clients
fulleni 1a351ac
refactor(notifications): simplify IPushNotificationClient interface
fulleni acfaf32
refactor(notifications): align Firebase client with new architecture
fulleni 3fea4a7
refactor(notifications): align OneSignal client with new architecture
fulleni 2fb5649
refactor(notifications): implement server-authoritative push logic
fulleni 036427b
refactor(notifications): implement fire-and-forget for breaking news
fulleni a6fba3f
feat(database): add unique indexes for push notification provider tokens
fulleni 3827b21
fix(notifications): remove unnecessary formatting and headers
fulleni 493e8cd
fix(database): correctly implement push notification config migration
fulleni f411cfd
style: format
fulleni 4b26c01
fix(firebase): replace Dio with HttpClient for OAuth token exchange
fulleni 569a8f7
refactor(dependencies): improve code structure and remove unused import
fulleni fe66da2
build(deps): update http-client to version 1.1.0
fulleni 80e87f9
style: format
fulleni 71d8b79
refactor(notifications): implement Firebase token provider for HTTP c…
fulleni 1e9ace6
Revert "refactor(notifications): implement Firebase token provider fo…
fulleni e47e4ab
refactor(firebase): extract Firebase access token logic into separate…
fulleni b8e03b2
fix(firebase_push_notification_client): improve error handling and lo…
fulleni 99e39bd
feat(auth): create dedicated FirebaseAuthenticator service
fulleni 44d4357
refactor(auth): integrate FirebaseAuthenticator service
fulleni 0d0edbe
refactor(auth): provide FirebaseAuthenticator in root middleware
fulleni 6c30ed5
refactor(config): make push credentials optional
fulleni 43c748f
refactor(push): implement conditional push notification client initia…
fulleni 5de379a
refactor(push): make notification service resilient to null clients
fulleni 7ec5e75
docs(env): update documentation for conditional environment variables
fulleni f0badfb
fix(auth): correct null-safety in firebase authenticator
fulleni ca9f23c
fix(deps): correct nullable provider and import order
fulleni 85150c4
style: format
fulleni 30d5d02
fix(config): treat empty env variables as null
fulleni File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
lib/src/database/migrations/20251107000000_add_is_breaking_to_headlines.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import 'package:flutter_news_app_api_server_full_source_code/src/database/migration.dart'; | ||
| import 'package:logging/logging.dart'; | ||
| import 'package:mongo_dart/mongo_dart.dart'; | ||
|
|
||
| /// Migration to add the `isBreaking` field to existing `Headline` documents. | ||
| /// | ||
| /// This migration ensures that all existing documents in the `headlines` | ||
| /// collection have the `isBreaking` boolean field, defaulting to `false` | ||
| /// if it does not already exist. This is crucial for schema consistency | ||
| /// when introducing the breaking news feature. | ||
| class AddIsBreakingToHeadlines extends Migration { | ||
| /// {@macro add_is_breaking_to_headlines} | ||
| AddIsBreakingToHeadlines() | ||
| : super( | ||
| prDate: '20251107000000', | ||
| prId: '71', | ||
| prSummary: | ||
| 'Adds the isBreaking field to existing Headline documents, ' | ||
| 'defaulting to false.', | ||
| ); | ||
|
|
||
| @override | ||
| Future<void> up(Db db, Logger log) async { | ||
| final collection = db.collection('headlines'); | ||
|
|
||
| log.info( | ||
| 'Attempting to add "isBreaking: false" to Headline documents ' | ||
| 'where the field is missing...', | ||
| ); | ||
|
|
||
| // Update all documents in the 'headlines' collection that do not | ||
| // already have the 'isBreaking' field, setting it to false. | ||
| final updateResult = await collection.updateMany( | ||
| // Select documents where 'isBreaking' does not exist. | ||
| where.notExists('isBreaking'), | ||
| modify.set('isBreaking', false), // Set isBreaking to false | ||
| ); | ||
|
|
||
| log.info( | ||
| 'Added "isBreaking: false" to ${updateResult.nModified} Headline documents.', | ||
| ); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> down(Db db, Logger log) async { | ||
| log.warning( | ||
| 'Reverting "AddIsBreakingToHeadlines" is not supported. ' | ||
| 'The "isBreaking" field would need to be manually removed if required.', | ||
| ); | ||
| } | ||
| } | ||
62 changes: 62 additions & 0 deletions
62
...src/database/migrations/20251108103300_add_push_notification_config_to_remote_config.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import 'package:core/core.dart'; | ||
| import 'package:flutter_news_app_api_server_full_source_code/src/database/migration.dart'; | ||
| import 'package:logging/logging.dart'; | ||
| import 'package:mongo_dart/mongo_dart.dart'; | ||
|
|
||
| /// {@template add_push_notification_config_to_remote_config} | ||
| /// A database migration to add the `pushNotificationConfig` field to the | ||
| /// `remote_configs` document. | ||
| /// | ||
| /// This migration ensures that the `remote_configs` document contains the | ||
| /// necessary structure for push notification settings, preventing errors when | ||
| /// the application starts and tries to access this configuration. It is | ||
| /// designed to be idempotent and safe to run multiple times. | ||
| /// {@endtemplate} | ||
| class AddPushNotificationConfigToRemoteConfig extends Migration { | ||
| /// {@macro add_push_notification_config_to_remote_config} | ||
| AddPushNotificationConfigToRemoteConfig() | ||
| : super( | ||
| prId: '71', | ||
| prSummary: | ||
| 'Add pushNotificationConfig field to the remote_configs document.', | ||
| prDate: '20251108103300', | ||
| ); | ||
|
|
||
| @override | ||
| Future<void> up(Db db, Logger log) async { | ||
| log.info('Running up migration: $prSummary'); | ||
|
|
||
| final remoteConfigCollection = db.collection('remote_configs'); | ||
| final remoteConfigId = ObjectId.fromHexString(kRemoteConfigId); | ||
|
|
||
| // Default structure for the push notification configuration. | ||
| final pushNotificationConfig = | ||
| remoteConfigsFixturesData.first.pushNotificationConfig; | ||
|
|
||
| // Use $set to add the field only if it doesn't exist. | ||
| // This is an idempotent operation. | ||
| await remoteConfigCollection.updateOne( | ||
| where | ||
| .id(remoteConfigId) | ||
| .and( | ||
| where.notExists('pushNotificationConfig'), | ||
| ), | ||
| modify.set('pushNotificationConfig', pushNotificationConfig.toJson()), | ||
| ); | ||
|
|
||
| log.info('Successfully completed up migration for $prDate.'); | ||
| } | ||
|
|
||
| @override | ||
| Future<void> down(Db db, Logger log) async { | ||
| log.info('Running down migration: $prSummary'); | ||
| // This migration is additive. The `down` method will unset the field. | ||
| final remoteConfigCollection = db.collection('remote_configs'); | ||
| final remoteConfigId = ObjectId.fromHexString(kRemoteConfigId); | ||
| await remoteConfigCollection.updateOne( | ||
| where.id(remoteConfigId), | ||
| modify.unset('pushNotificationConfig'), | ||
| ); | ||
| log.info('Successfully completed down migration for $prDate.'); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.