Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
61 changes: 61 additions & 0 deletions app/lib/admin/actions/package_publisher_set.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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 {'publisherId': pkg!.publisherId};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we return the previous publisher/uploader also?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

},
);
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.

14 changes: 14 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,19 @@ 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, {'publisherId': 'example.com'});
},
);
});
}