Skip to content

Commit d4c325e

Browse files
authored
List and delete admin action for package reservation. (#8121)
1 parent 4a73f21 commit d4c325e

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

app/lib/admin/actions/actions.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import 'moderation_case_update.dart';
2020
import 'moderation_transparency_metrics.dart';
2121
import 'package_info.dart';
2222
import 'package_reservation_create.dart';
23+
import 'package_reservation_delete.dart';
24+
import 'package_reservation_list.dart';
2325
import 'package_version_info.dart';
2426
import 'package_version_retraction.dart';
2527
import 'publisher_block.dart';
@@ -102,6 +104,8 @@ final class AdminAction {
102104
moderationTransparencyMetrics,
103105
packageInfo,
104106
packageReservationCreate,
107+
packageReservationDelete,
108+
packageReservationList,
105109
packageVersionInfo,
106110
packageVersionRetraction,
107111
publisherBlock,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:pub_dev/package/backend.dart';
6+
import 'package:pub_dev/shared/datastore.dart';
7+
8+
import 'actions.dart';
9+
10+
final packageReservationDelete = AdminAction(
11+
name: 'package-reservation-delete',
12+
summary: 'Deletes a ReservedPackage entity.',
13+
description: '''
14+
Deletes a ReservedPackage entity, allowing the package name use by any user.
15+
''',
16+
options: {
17+
'package': 'The package reservation to be deleted.',
18+
},
19+
invoke: (options) async {
20+
final package = options['package'];
21+
InvalidInputException.check(
22+
package != null && package.isNotEmpty,
23+
'`package` must be given',
24+
);
25+
26+
final rp = await packageBackend.lookupReservedPackage(package!);
27+
if (rp == null) {
28+
throw NotFoundException('ReservedPackage `$package` does not exist.');
29+
}
30+
31+
await dbService.commit(deletes: [rp.key]);
32+
33+
return {
34+
'ReservedPackage': {
35+
'name': rp.name,
36+
'emails': rp.emails,
37+
'deleted': true,
38+
},
39+
};
40+
},
41+
);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:pub_dev/package/models.dart';
6+
import 'package:pub_dev/shared/datastore.dart';
7+
8+
import 'actions.dart';
9+
10+
final packageReservationList = AdminAction(
11+
name: 'package-reservation-list',
12+
summary: 'Lists all ReservedPackage entities.',
13+
description: '''
14+
Returns the list of all ReservedPackage entities and the allowed emails.
15+
''',
16+
options: {},
17+
invoke: (options) async {
18+
final query = dbService.query<ReservedPackage>();
19+
final list = await query.run().toList();
20+
21+
return {
22+
'packages': list
23+
.map((rp) => {
24+
'name': rp.name,
25+
'emails': rp.emails,
26+
})
27+
.toList(),
28+
};
29+
},
30+
);

app/test/admin/package_reservation_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,23 @@ void main() {
3030
);
3131
}
3232

33+
Future<Map<String, dynamic>> _list() async {
34+
final api = createPubApiClient(authToken: siteAdminToken);
35+
final rs = await api.adminInvokeAction(
36+
'package-reservation-list',
37+
AdminInvokeActionArguments(arguments: {}),
38+
);
39+
return rs.output;
40+
}
41+
42+
Future<void> _delete(String package) async {
43+
final api = createPubApiClient(authToken: siteAdminToken);
44+
await api.adminInvokeAction(
45+
'package-reservation-delete',
46+
AdminInvokeActionArguments(arguments: {'package': package}),
47+
);
48+
}
49+
3350
testWithProfile('cannot reserve existing package', fn: () async {
3451
await expectApiException(
3552
_reserve('oxygen'),
@@ -97,5 +114,19 @@ void main() {
97114
message: 'Package name pkg is reserved.',
98115
);
99116
});
117+
118+
testWithProfile('list and delete', fn: () async {
119+
await _reserve('pkg', emails: ['[email protected]']);
120+
expect(await _list(), {
121+
'packages': [
122+
{
123+
'name': 'pkg',
124+
'emails': ['[email protected]'],
125+
}
126+
]
127+
});
128+
await _delete('pkg');
129+
expect(await _list(), {'packages': []});
130+
});
100131
});
101132
}

0 commit comments

Comments
 (0)