Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions app/lib/admin/actions/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:pub_dev/admin/actions/package_invite_uploader.dart';

import '../../shared/exceptions.dart';
import 'download_counts_backfill.dart';
import 'download_counts_delete.dart';
Expand All @@ -24,7 +22,9 @@ import 'moderation_transparency_metrics.dart';
import 'package_delete.dart';
import 'package_discontinue.dart';
import 'package_info.dart';
import 'package_invite_uploader.dart';
import 'package_latest_update.dart';
import 'package_publisher_set.dart';
import 'package_reservation_create.dart';
import 'package_reservation_delete.dart';
import 'package_reservation_list.dart';
Expand Down Expand Up @@ -115,6 +115,7 @@ final class AdminAction {
packageInfo,
packageInviteUploader,
packageLatestUpdate,
packagePublisherSet,
packageReservationCreate,
packageReservationDelete,
packageReservationList,
Expand Down
64 changes: 64 additions & 0 deletions app/lib/admin/actions/package_publisher_set.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:clock/clock.dart';
import 'package:pub_dev/package/backend.dart';
import 'package:pub_dev/package/models.dart';
import 'package:pub_dev/publisher/backend.dart';
import 'package:pub_dev/shared/datastore.dart';

import 'actions.dart';

final packagePublisherSet = AdminAction(
name: 'package-publisher-set',
summary: 'Sets the publisher for a package.',
description: 'Sets a new `publisherId` for a `package`.',
options: {
'package': 'The package to be updated.',
'publisher': 'The `publisherId` to set.',
},
invoke: (options) async {
final packageName = options['package'];
final publisherId = options['publisher'];

if (packageName == null) {
throw InvalidInputException('Missing --package argument.');
}
if (publisherId == null) {
throw InvalidInputException('Missing --publisher argument.');
}

final package = (await packageBackend.lookupPackage(packageName))!;
final publisher = await publisherBackend.lookupPublisher(publisherId);
if (publisher == null || !publisher.isVisible) {
InvalidInputException(
'Publisher `$publisherId` does not exists or is not visible.',
);
}
final currentPublisherId = package.publisherId;
if (currentPublisherId != publisherId) {
await withRetryTransaction(dbService, (tx) async {
final pkg = await tx.lookupValue<Package>(package.key);
pkg.publisherId = publisherId;
pkg.updated = clock.now().toUtc();
tx.insert(pkg);
});
await purgePublisherCache(publisherId: publisherId);
triggerPackagePostUpdates(
packageName,
skipReanalysis: true,
skipVersionsExport: true,
);
if (currentPublisherId != null) {
await purgePublisherCache(publisherId: currentPublisherId);
}
}

final pkg = await packageBackend.lookupPackage(packageName);
return {
'before': {'publisherId': currentPublisherId},
'after': {'publisherId': pkg!.publisherId},
};
},
);
2 changes: 0 additions & 2 deletions app/lib/admin/backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import 'actions/actions.dart' show AdminAction;
import 'tools/delete_all_staging.dart';
import 'tools/list_tools.dart';
import 'tools/notify_service.dart';
import 'tools/package_publisher.dart';
import 'tools/recent_uploaders.dart';
import 'tools/user_merger.dart';

Expand All @@ -55,7 +54,6 @@ typedef Tool = Future<String> Function(List<String> args);
final Map<String, Tool> availableTools = {
'delete-all-staging': executeDeleteAllStaging,
'notify-service': executeNotifyService,
'package-publisher': executeSetPackagePublisher,
'recent-uploaders': executeRecentUploaders,
'user-merger': executeUserMergerTool,
'list-tools': executeListTools,
Expand Down
54 changes: 0 additions & 54 deletions app/lib/admin/tools/package_publisher.dart

This file was deleted.

17 changes: 17 additions & 0 deletions app/test/admin/package_actions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,22 @@ void main() {
expect(rs.output, {'updatedCount': 0});
},
);

testWithProfile(
'set publisher on a package',
fn: () async {
final client = createPubApiClient(authToken: siteAdminToken);
final rs = await client.adminInvokeAction(
'package-publisher-set',
AdminInvokeActionArguments(
arguments: {'package': 'oxygen', 'publisher': 'example.com'},
),
);
expect(rs.output, {
'before': {'publisherId': null},
'after': {'publisherId': 'example.com'},
});
},
);
});
}