@@ -67,11 +67,11 @@ class AppDependencies {
6767 late final DataRepository <User > userRepository;
6868 late final DataRepository <UserAppSettings > userAppSettingsRepository;
6969 late final DataRepository <UserContentPreferences >
70- userContentPreferencesRepository;
70+ userContentPreferencesRepository;
7171 late final DataRepository <PushNotificationDevice >
72- pushNotificationDeviceRepository;
72+ pushNotificationDeviceRepository;
7373 late final DataRepository <PushNotificationSubscription >
74- pushNotificationSubscriptionRepository;
74+ pushNotificationSubscriptionRepository;
7575 late final DataRepository <RemoteConfig > remoteConfigRepository;
7676 late final EmailRepository emailRepository;
7777
@@ -87,9 +87,9 @@ class AppDependencies {
8787 late final RateLimitService rateLimitService;
8888 late final CountryQueryService countryQueryService;
8989 late final IPushNotificationService pushNotificationService;
90- late final IFirebaseAuthenticator firebaseAuthenticator;
91- late final IPushNotificationClient firebasePushNotificationClient;
92- late final IPushNotificationClient oneSignalPushNotificationClient;
90+ late final IFirebaseAuthenticator ? firebaseAuthenticator;
91+ late final IPushNotificationClient ? firebasePushNotificationClient;
92+ late final IPushNotificationClient ? oneSignalPushNotificationClient;
9393
9494 /// Initializes all application dependencies.
9595 ///
@@ -222,51 +222,78 @@ class AppDependencies {
222222 );
223223 final pushNotificationSubscriptionClient =
224224 DataMongodb <PushNotificationSubscription >(
225- connectionManager: _mongoDbConnectionManager,
226- modelName: 'push_notification_subscriptions' ,
227- fromJson: PushNotificationSubscription .fromJson,
228- toJson: (item) => item.toJson (),
229- logger: Logger ('DataMongodb<PushNotificationSubscription>' ),
230- );
231-
232- // --- Initialize Firebase Authenticator ---
233- // This dedicated service encapsulates the logic for obtaining a Firebase
234- // access token, keeping the dependency setup clean.
235- firebaseAuthenticator = FirebaseAuthenticator (
236- log: Logger ('FirebaseAuthenticator' ),
237- );
238-
239- // --- Initialize HTTP clients for push notification providers ---
240-
241- // The Firebase client requires a short-lived OAuth2 access token. This
242- // tokenProvider implements the required two-legged OAuth flow:
243- // 1. Create a JWT signed with the service account's private key.
244- // 2. Exchange this JWT for an access token from Google's token endpoint.
245- final firebaseHttpClient = HttpClient (
246- baseUrl:
247- 'https://fcm.googleapis.com/v1/projects/${EnvironmentConfig .firebaseProjectId }/' ,
248- tokenProvider: firebaseAuthenticator.getAccessToken,
249- logger: Logger ('FirebasePushNotificationClient' ),
250- );
225+ connectionManager: _mongoDbConnectionManager,
226+ modelName: 'push_notification_subscriptions' ,
227+ fromJson: PushNotificationSubscription .fromJson,
228+ toJson: (item) => item.toJson (),
229+ logger: Logger ('DataMongodb<PushNotificationSubscription>' ),
230+ );
231+
232+ // --- Conditionally Initialize Push Notification Clients ---
233+
234+ // Firebase
235+ final fcmProjectId = EnvironmentConfig .firebaseProjectId;
236+ final fcmClientEmail = EnvironmentConfig .firebaseClientEmail;
237+ final fcmPrivateKey = EnvironmentConfig .firebasePrivateKey;
238+
239+ if (fcmProjectId != null &&
240+ fcmClientEmail != null &&
241+ fcmPrivateKey != null ) {
242+ _log.info ('Firebase credentials found. Initializing Firebase client.' );
243+ firebaseAuthenticator =
244+ FirebaseAuthenticator (log: Logger ('FirebaseAuthenticator' ));
245+
246+ final firebaseHttpClient = HttpClient (
247+ baseUrl: 'https://fcm.googleapis.com/v1/projects/$fcmProjectId /' ,
248+ tokenProvider: firebaseAuthenticator! .getAccessToken,
249+ logger: Logger ('FirebasePushNotificationClient' ),
250+ );
251+
252+ firebasePushNotificationClient = FirebasePushNotificationClient (
253+ httpClient: firebaseHttpClient,
254+ projectId: fcmProjectId,
255+ log: Logger ('FirebasePushNotificationClient' ),
256+ );
257+ } else {
258+ _log.warning (
259+ 'One or more Firebase credentials not found. Firebase push notifications will be disabled.' ,
260+ );
261+ firebaseAuthenticator = null ;
262+ firebasePushNotificationClient = null ;
263+ }
264+
265+ // OneSignal
266+ final osAppId = EnvironmentConfig .oneSignalAppId;
267+ final osApiKey = EnvironmentConfig .oneSignalRestApiKey;
268+
269+ if (osAppId != null && osApiKey != null ) {
270+ _log.info ('OneSignal credentials found. Initializing OneSignal client.' );
271+ final oneSignalHttpClient = HttpClient (
272+ baseUrl: 'https://onesignal.com/api/v1/' ,
273+ tokenProvider: () async => null ,
274+ interceptors: [
275+ InterceptorsWrapper (
276+ onRequest: (options, handler) {
277+ options.headers['Authorization' ] = 'Basic $osApiKey ' ;
278+ return handler.next (options);
279+ },
280+ ),
281+ ],
282+ logger: Logger ('OneSignalPushNotificationClient' ),
283+ );
284+
285+ oneSignalPushNotificationClient = OneSignalPushNotificationClient (
286+ httpClient: oneSignalHttpClient,
287+ appId: osAppId,
288+ log: Logger ('OneSignalPushNotificationClient' ),
289+ );
290+ } else {
291+ _log.warning (
292+ 'One or more OneSignal credentials not found. OneSignal push notifications will be disabled.' ,
293+ );
294+ oneSignalPushNotificationClient = null ;
295+ }
251296
252- // The OneSignal client requires the REST API key for authentication.
253- // We use a custom interceptor to add the 'Authorization: Basic <API_KEY>'
254- // header, as the default AuthInterceptor is hardcoded for 'Bearer' tokens.
255- final oneSignalHttpClient = HttpClient (
256- baseUrl: 'https://onesignal.com/api/v1/' ,
257- // The tokenProvider is not used here; auth is handled by the interceptor.
258- tokenProvider: () async => null ,
259- interceptors: [
260- InterceptorsWrapper (
261- onRequest: (options, handler) {
262- options.headers['Authorization' ] =
263- 'Basic ${EnvironmentConfig .oneSignalRestApiKey }' ;
264- return handler.next (options);
265- },
266- ),
267- ],
268- logger: Logger ('OneSignalPushNotificationClient' ),
269- );
270297 // 4. Initialize Repositories
271298 headlineRepository = DataRepository (dataClient: headlineClient);
272299 topicRepository = DataRepository (dataClient: topicClient);
@@ -306,18 +333,6 @@ class AppDependencies {
306333
307334 emailRepository = EmailRepository (emailClient: emailClient);
308335
309- // Initialize Push Notification Clients
310- firebasePushNotificationClient = FirebasePushNotificationClient (
311- httpClient: firebaseHttpClient,
312- projectId: EnvironmentConfig .firebaseProjectId,
313- log: Logger ('FirebasePushNotificationClient' ),
314- );
315- oneSignalPushNotificationClient = OneSignalPushNotificationClient (
316- httpClient: oneSignalHttpClient,
317- appId: EnvironmentConfig .oneSignalAppId,
318- log: Logger ('OneSignalPushNotificationClient' ),
319- );
320-
321336 // 5. Initialize Services
322337 tokenBlacklistService = MongoDbTokenBlacklistService (
323338 connectionManager: _mongoDbConnectionManager,
0 commit comments