Skip to content

Commit e141a59

Browse files
authored
Merge pull request #91 from flutter-news-app-full-source-code/feat/deprecated-local-ads-db-migration
Feat/deprecated local ads db migration
2 parents 1486232 + 998a374 commit e141a59

File tree

11 files changed

+88
-98
lines changed

11 files changed

+88
-98
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
<!--
2-
Thanks for contributing!
3-
4-
Provide a description of your changes below and a general summary in the title
5-
6-
Please look at the following checklist to ensure that your PR can be accepted quickly:
7-
-->
8-
91
## Status
102

113
**READY/IN DEVELOPMENT/HOLD**

lib/src/config/app_dependencies.dart

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class AppDependencies {
6363
late final DataRepository<UserContentPreferences>
6464
userContentPreferencesRepository;
6565
late final DataRepository<RemoteConfig> remoteConfigRepository;
66-
late final DataRepository<LocalAd> localAdRepository;
6766
late final EmailRepository emailRepository;
6867

6968
// Services
@@ -232,16 +231,6 @@ class AppDependencies {
232231

233232
emailRepository = EmailRepository(emailClient: emailClient);
234233

235-
final localAdClient = DataMongodb<LocalAd>(
236-
connectionManager: _mongoDbConnectionManager,
237-
modelName: 'local_ads',
238-
fromJson: LocalAd.fromJson,
239-
toJson: LocalAd.toJson,
240-
searchableFields: ['title'],
241-
logger: Logger('DataMongodb<LocalAd>'),
242-
);
243-
localAdRepository = DataRepository(dataClient: localAdClient);
244-
245234
// 5. Initialize Services
246235
tokenBlacklistService = MongoDbTokenBlacklistService(
247236
connectionManager: _mongoDbConnectionManager,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import 'package:flutter_news_app_api_server_full_source_code/src/database/migration.dart';
2+
import 'package:logging/logging.dart';
3+
import 'package:mongo_dart/mongo_dart.dart';
4+
5+
/// Migration to remove the legacy `local` ad platform from the `remote_configs`
6+
/// collection.
7+
///
8+
/// This migration performs two critical cleanup tasks:
9+
/// 1. It removes the `local` key from the `adConfig.platformAdIdentifiers` map
10+
/// in all `remote_configs` documents.
11+
/// 2. It updates any `remote_configs` document where the `primaryAdPlatform`
12+
/// is set to `local`, changing it to `admob`.
13+
///
14+
/// This ensures data consistency after the removal of the `AdPlatformType.local`
15+
/// enum value and prevents deserialization errors in the application.
16+
class RemoveLocalAdPlatform extends Migration {
17+
/// {@macro remove_local_ad_platform}
18+
RemoveLocalAdPlatform()
19+
: super(
20+
prDate: '20251103073226',
21+
prId: '57',
22+
prSummary:
23+
'Removes the legacy local ad platform from the remote config, migrating existing data to use admob as the default.',
24+
);
25+
26+
@override
27+
Future<void> up(Db db, Logger log) async {
28+
final collection = db.collection('remote_configs');
29+
30+
// Step 1: Unset the 'local' key from the platformAdIdentifiers map.
31+
// This removes the field entirely from any document where it exists.
32+
log.info(
33+
'Attempting to remove "adConfig.platformAdIdentifiers.local" field...',
34+
);
35+
final unsetResult = await collection.updateMany(
36+
where.exists('adConfig.platformAdIdentifiers.local'),
37+
modify.unset('adConfig.platformAdIdentifiers.local'),
38+
);
39+
log.info(
40+
'Removed "adConfig.platformAdIdentifiers.local" from ${unsetResult.nModified} documents.',
41+
);
42+
43+
// Step 2: Update the primaryAdPlatform from 'local' to 'admob'.
44+
// This ensures that no document is left with an invalid primary platform.
45+
log.info(
46+
'Attempting to migrate primaryAdPlatform from "local" to "admob"...',
47+
);
48+
final updateResult = await collection.updateMany(
49+
where.eq('adConfig.primaryAdPlatform', 'local'),
50+
modify.set('adConfig.primaryAdPlatform', 'admob'),
51+
);
52+
log.info(
53+
'Migrated primaryAdPlatform to "admob" for ${updateResult.nModified} documents.',
54+
);
55+
}
56+
57+
@override
58+
Future<void> down(Db db, Logger log) async {
59+
// Reverting this change is not safe as it would require re-introducing
60+
// an enum value that no longer exists in the code.
61+
log.warning(
62+
'Reverting "RemoveLocalAdPlatform" is not supported. The "local" ad platform configuration would need to be manually restored if required.',
63+
);
64+
}
65+
}

lib/src/database/migrations/all_migrations.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:flutter_news_app_api_server_full_source_code/src/database/migrat
33
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20251013000056_add_saved_filters_to_user_preferences.dart';
44
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20251013000057_add_saved_filters_to_remote_config.dart';
55
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20251024000000_add_logo_url_to_sources.dart';
6+
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20251103073226_remove_local_ad_platform.dart';
67
import 'package:flutter_news_app_api_server_full_source_code/src/services/database_migration_service.dart'
78
show DatabaseMigrationService;
89

@@ -16,4 +17,5 @@ final List<Migration> allMigrations = [
1617
AddSavedFiltersToUserPreferences(),
1718
AddSavedFiltersToRemoteConfig(),
1819
AddLogoUrlToSources(),
20+
RemoveLocalAdPlatform(),
1921
];

lib/src/registry/data_operation_registry.dart

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ typedef ItemUpdater =
4444
typedef ItemDeleter =
4545
Future<void> Function(RequestContext context, String id, String? userId);
4646

47+
final _log = Logger('DataOperationRegistry');
48+
4749
/// {@template data_operation_registry}
4850
/// A centralized registry for all data handling functions (CRUD operations).
4951
///
@@ -56,12 +58,12 @@ typedef ItemDeleter =
5658
/// data operations are performed for each model, improving consistency across
5759
/// the API.
5860
/// {@endtemplate}
59-
60-
final _log = Logger('DataOperationRegistry');
61-
6261
class DataOperationRegistry {
6362
/// {@macro data_operation_registry}
6463
DataOperationRegistry() {
64+
_log.info(
65+
'Initializing DataOperationRegistry.',
66+
);
6567
_registerOperations();
6668
}
6769

@@ -113,8 +115,6 @@ class DataOperationRegistry {
113115
.read(id: id, userId: null),
114116
'remote_config': (c, id) =>
115117
c.read<DataRepository<RemoteConfig>>().read(id: id, userId: null),
116-
'local_ad': (c, id) =>
117-
c.read<DataRepository<LocalAd>>().read(id: id, userId: null),
118118
'dashboard_summary': (c, id) =>
119119
c.read<DashboardSummaryService>().getSummary(),
120120
});
@@ -166,9 +166,6 @@ class DataOperationRegistry {
166166
sort: s,
167167
pagination: p,
168168
),
169-
'local_ad': (c, uid, f, s, p) => c
170-
.read<DataRepository<LocalAd>>()
171-
.readAll(userId: uid, filter: f, sort: s, pagination: p),
172169
});
173170

174171
// --- Register Item Creators ---
@@ -196,10 +193,6 @@ class DataOperationRegistry {
196193
'remote_config': (c, item, uid) => c
197194
.read<DataRepository<RemoteConfig>>()
198195
.create(item: item as RemoteConfig, userId: uid),
199-
'local_ad': (c, item, uid) => c.read<DataRepository<LocalAd>>().create(
200-
item: item as LocalAd,
201-
userId: uid,
202-
),
203196
});
204197

205198
// --- Register Item Updaters ---
@@ -319,9 +312,6 @@ class DataOperationRegistry {
319312
'remote_config': (c, id, item, uid) => c
320313
.read<DataRepository<RemoteConfig>>()
321314
.update(id: id, item: item as RemoteConfig, userId: uid),
322-
'local_ad': (c, id, item, uid) => c
323-
.read<DataRepository<LocalAd>>()
324-
.update(id: id, item: item as LocalAd, userId: uid),
325315
});
326316

327317
// --- Register Item Deleters ---
@@ -343,8 +333,6 @@ class DataOperationRegistry {
343333
.delete(id: id, userId: uid),
344334
'remote_config': (c, id, uid) =>
345335
c.read<DataRepository<RemoteConfig>>().delete(id: id, userId: uid),
346-
'local_ad': (c, id, uid) =>
347-
c.read<DataRepository<LocalAd>>().delete(id: id, userId: uid),
348336
});
349337
}
350338
}

lib/src/registry/model_registry.dart

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -425,36 +425,6 @@ final modelRegistry = <String, ModelConfig<dynamic>>{
425425
requiresAuthentication: true,
426426
),
427427
),
428-
'local_ad': ModelConfig<LocalAd>(
429-
fromJson: LocalAd.fromJson,
430-
getId: (ad) => ad.id,
431-
getOwnerId: null, // LocalAd is a global resource, not user-owned
432-
getCollectionPermission: const ModelActionPermission(
433-
type: RequiredPermissionType.specificPermission,
434-
permission: Permissions.localAdRead,
435-
requiresAuthentication: true,
436-
),
437-
getItemPermission: const ModelActionPermission(
438-
type: RequiredPermissionType.specificPermission,
439-
permission: Permissions.localAdRead,
440-
requiresAuthentication: true,
441-
),
442-
postPermission: const ModelActionPermission(
443-
type: RequiredPermissionType.adminOnly,
444-
permission: Permissions.localAdCreate,
445-
requiresAuthentication: true,
446-
),
447-
putPermission: const ModelActionPermission(
448-
type: RequiredPermissionType.adminOnly,
449-
permission: Permissions.localAdUpdate,
450-
requiresAuthentication: true,
451-
),
452-
deletePermission: const ModelActionPermission(
453-
type: RequiredPermissionType.adminOnly,
454-
permission: Permissions.localAdDelete,
455-
requiresAuthentication: true,
456-
),
457-
),
458428
};
459429

460430
/// Type alias for the ModelRegistry map for easier provider usage.

lib/src/services/database_seeding_service.dart

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,6 @@ class DatabaseSeedingService {
4040
getId: (item) => item.id,
4141
toJson: (item) => item.toJson(),
4242
);
43-
await _seedCollection<LocalAd>(
44-
collectionName: 'local_ads',
45-
fixtureData: localAdsFixturesData,
46-
getId: (ad) => ad.id,
47-
// ignore: unnecessary_lambdas
48-
toJson: (item) => LocalAd.toJson(item),
49-
);
5043

5144
_log.info('Database seeding process completed.');
5245
}
@@ -130,7 +123,7 @@ class DatabaseSeedingService {
130123
// Ensure primaryAdPlatform is not 'demo' for initial setup
131124
// since its not intended for any use outside the mobile client.
132125
final productionReadyAdConfig = initialConfig.adConfig.copyWith(
133-
primaryAdPlatform: AdPlatformType.local,
126+
primaryAdPlatform: AdPlatformType.admob,
134127
);
135128

136129
final productionReadyConfig = initialConfig.copyWith(
@@ -191,13 +184,6 @@ class DatabaseSeedingService {
191184
.collection('countries')
192185
.createIndex(keys: {'name': 1}, name: 'countries_name_index');
193186

194-
/// Index for searching local ads by adType.
195-
/// This index supports efficient queries and filtering on the 'adType' field
196-
/// of local ad documents.
197-
await _db
198-
.collection('local_ads')
199-
.createIndex(keys: {'adType': 1}, name: 'local_ads_adType_index');
200-
201187
// --- TTL and Unique Indexes via runCommand ---
202188
// The following indexes are created using the generic `runCommand` because
203189
// they require specific options not exposed by the simpler `createIndex`

pubspec.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ packages:
2121
dependency: transitive
2222
description:
2323
name: analyzer
24-
sha256: a40a0cee526a7e1f387c6847bd8a5ccbf510a75952ef8a28338e989558072cb0
24+
sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08
2525
url: "https://pub.dev"
2626
source: hosted
27-
version: "8.4.0"
27+
version: "8.4.1"
2828
archive:
2929
dependency: transitive
3030
description:
@@ -117,8 +117,8 @@ packages:
117117
dependency: "direct main"
118118
description:
119119
path: "."
120-
ref: "v1.3.1"
121-
resolved-ref: a03efff11b7577974cb444a1a6a46fee8b05ea42
120+
ref: e7c808c9d459233196e2eac3137a9c87d3976af3
121+
resolved-ref: e7c808c9d459233196e2eac3137a9c87d3976af3
122122
url: "https://github.com/flutter-news-app-full-source-code/core.git"
123123
source: git
124124
version: "1.3.1"
@@ -142,10 +142,10 @@ packages:
142142
dependency: "direct main"
143143
description:
144144
name: dart_frog
145-
sha256: "0fc909d10ae79dd069e6a3a4769aeaa9839c93b7f6f1e71cfd37b276410875e7"
145+
sha256: "87b5280b029aa2f80f5e9954db4b6c7cbbc2ae6adf5579150c11c40829f95a0a"
146146
url: "https://pub.dev"
147147
source: hosted
148-
version: "1.2.4"
148+
version: "1.2.5"
149149
dart_jsonwebtoken:
150150
dependency: "direct main"
151151
description:

pubspec.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,8 @@ dev_dependencies:
5555
test: ^1.25.5
5656
very_good_analysis: ^9.0.0
5757

58+
dependency_overrides:
59+
core:
60+
git:
61+
url: https://github.com/flutter-news-app-full-source-code/core.git
62+
ref: e7c808c9d459233196e2eac3137a9c87d3976af3

routes/_middleware.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,6 @@ Handler middleware(Handler handler) {
127127
(_) => deps.remoteConfigRepository,
128128
),
129129
)
130-
.use(
131-
provider<DataRepository<LocalAd>>(
132-
(_) => deps.localAdRepository,
133-
),
134-
)
135130
.use(provider<EmailRepository>((_) => deps.emailRepository))
136131
.use(
137132
provider<TokenBlacklistService>(

0 commit comments

Comments
 (0)