Skip to content

Commit

Permalink
Merge pull request pd4d10#5 from bilaldbank/feat/remove-package
Browse files Browse the repository at this point in the history
#866aa0wkr add endpoint for removing package
  • Loading branch information
tasnim-din authored May 22, 2023
2 parents 0bfe3a1 + ba2fcce commit 39bb9bd
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 2 deletions.
42 changes: 40 additions & 2 deletions unpub/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class App {
final Future<void> Function(
Map<String, dynamic> pubspec, String uploaderEmail)? uploadValidator;

/// start time of the server
final DateTime startTime;

App({
required this.metaStore,
required this.packageStore,
Expand All @@ -59,7 +62,7 @@ class App {
this.uploadValidator,
this.proxy_origin,
this.opaqueToken,
});
}) : startTime = DateTime.now();

static shelf.Response _okWithJson(Map<String, dynamic> data) =>
shelf.Response.ok(
Expand Down Expand Up @@ -379,6 +382,32 @@ class App {
return _successMessage('uploader removed');
}

@Route.delete('/api/packages/<name>')
Future<shelf.Response> removePackage(shelf.Request req, String name) async {
try {
await _validateOpaqueToken(req);

final package = await metaStore.queryPackage(name);

if (package == null) {
return _badRequest('package not found');
}

/// TODO: Throw exception if other packages depend on this

/// Remove files
final versions = package.versions.map((v) => v.version).toList();
await packageStore.remove(package.name, versions);

/// Remove metadata (after removing the package tars)
await metaStore.removePackage(package.name);
return _successMessage('package removed');
} catch (err) {
return _badRequest(err.toString());
}
}

@Route.get('/webapi/packages')
Future<shelf.Response> getPackages(shelf.Request req) async {
var params = req.requestedUri.queryParameters;
Expand Down Expand Up @@ -510,10 +539,19 @@ class App {
@Route.get('/packages/<name>')
@Route.get('/packages/<name>/versions/<version>')
Future<shelf.Response> indexHtml(shelf.Request req) async {
return shelf.Response.ok(index_html.content,
final updatedHtmlContent = _addStartTimeInHtml();

return shelf.Response.ok(updatedHtmlContent,
headers: {HttpHeaders.contentTypeHeader: ContentType.html.mimeType});
}

/// Update the title in HTML to include server start time
String _addStartTimeInHtml() {
final updatedHtml = index_html.content
.replaceFirst('<title>Unpub', '<title>Unpub $startTime');
return updatedHtml;
}

@Route.get('/main.dart.js')
Future<shelf.Response> mainDartJs(shelf.Request req) async {
return shelf.Response.ok(main_dart_js.content,
Expand Down
5 changes: 5 additions & 0 deletions unpub/lib/src/app.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions unpub/lib/src/file_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ class FileStore extends PackageStore {
Stream<List<int>> download(String name, String version) {
return _getTarballFile(name, version).openRead();
}

@override
Future<void> remove(String name, List<String> versions) async {
final files = versions.map((v) => _getTarballFile(name, v)).toList();
await Future.wait(files.map((e) => e.delete()));
}
}
2 changes: 2 additions & 0 deletions unpub/lib/src/meta_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ abstract class MetaStore {
String? uploader,
String? dependency,
});

Future<void> removePackage(String name);
}
5 changes: 5 additions & 0 deletions unpub/lib/src/mongo_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,9 @@ class MongoStore extends MetaStore {

return _queryPackagesBySelector(selector);
}

@override
removePackage(String name) async {
await db.collection(packageCollection).deleteOne(_selectByName(name));
}
}
2 changes: 2 additions & 0 deletions unpub/lib/src/package_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ abstract class PackageStore {
}

Future<void> upload(String name, String version, List<int> content);

Future<void> remove(String name, List<String> versions);
}
27 changes: 27 additions & 0 deletions unpub/test/unpub_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,33 @@ main() {
});
});

group('remove package', () {
setUpAll(() async {
await _cleanUpDb();
_server = await createServer(email0);
await pubPublish(package0, '0.0.1');
});

tearDownAll(() async {
await _server.close();
});

test('remove existing package', () async {
final initialRes = await getVersions(package0);
expect(initialRes.statusCode, HttpStatus.ok);

await removePackage(package0);

final response = await getVersions(package0);
expect(response.statusCode, HttpStatus.notFound);
});

test('remove non-existant package', () async {
final res = await removePackage(notExistingPacakge);
expect(res.statusCode, HttpStatus.badRequest);
});
});

group('uploader', () {
setUpAll(() async {
await _cleanUpDb();
Expand Down
5 changes: 5 additions & 0 deletions unpub/test/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ Future<ProcessResult> pubPublish(String name, String version) {
environment: {'PUB_HOSTED_URL': pubHostedUrl});
}

Future<http.Response> removePackage(String name){
final encodedName = Uri.encodeComponent(name);
return http.delete(baseUri.resolve('/api/packages/$encodedName'));
}

Future<ProcessResult> pubUploader(String name, String operation, String email) {
assert(['add', 'remove'].contains(operation), 'operation error');

Expand Down

0 comments on commit 39bb9bd

Please sign in to comment.