PypiArtifactController extends BaseArtifactController { @ApiOperation(value = "This Endpoint will be used to retreive all the versions of packages present in artifactory.") @ApiResponses(value = { @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Success"), @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Request Url Not Found"), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "An error occurred while executing download request."), @ApiResponse(code = HttpURLConnection.HTTP_UNAVAILABLE, message = "Service Unavailable.") }) @PreAuthorize("hasAuthority('ARTIFACTS_RESOLVE')") @RequestMapping(path = "/{storageId}/{repositoryId}/simple/{packageName}", method = RequestMethod.GET, produces = MediaType.TEXT_HTML) public ResponseEntity<String> browsePackage(@RepositoryMapping Repository repository, @PathVariable(name = "packageName") String packageName, HttpServletRequest request, HttpServletResponse response, @RequestHeader HttpHeaders headers) throws Exception { final String packageNameToDownload = PypiPackageNameConverter.escapeSpecialCharacters(packageName); logger.info("Get package path request for storageId -> [{}] , repositoryId -> [{}], packageName -> [{}]", repository.getStorage().getId(), repository.getId(), packageNameToDownload); RepositoryProvider repositoryProvider = repositoryProviderRegistry.getProvider(repository.getType()); Predicate predicate = Predicate.empty(); predicate.and(Predicate.of(ExpOperator.EQ.of("artifactCoordinates.coordinates.packaging", PypiArtifactCoordinates.WHEEL_EXTENSION))); predicate.and(Predicate.of(ExpOperator.EQ.of("artifactCoordinates.coordinates.distribution", packageNameToDownload))); Paginator paginator = new Paginator(); List<Path> searchResult = repositoryProvider.search(repository.getStorage().getId(), repository.getId(), predicate, paginator); String searchPackageHtmlResponse = htmlResponseBuilder.getHtmlResponse(searchResult); return ResponseEntity.status(HttpStatus.OK).body(searchPackageHtmlResponse); }  @ApiOperation(value = "This end point will be used to upload/deploy python package.") @ApiResponses(value = { @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "python package was deployed successfully."), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "An error occurred while executing request."), @ApiResponse(code = HttpURLConnection.HTTP_UNAVAILABLE, message = "Service Unavailable.") }) @PreAuthorize("hasAuthority('ARTIFACTS_DEPLOY')") @RequestMapping(path = "/{storageId}/{repositoryId}", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA) ResponseEntity<String> uploadPackage(
                                                @RepositoryMapping Repository repository,
                                                @RequestPart(name = "comment", required = false) String comment,
                                                @RequestPart(name = "metadata_version", required = true) String metadataVersion,
                                                @RequestPart(name = "filetype", required = true) String filetype,
                                                @RequestPart(name = "protcol_version", required = false) String protcolVersion,
                                                @RequestPart(name = "author", required = false) String author,
                                                @RequestPart(name = "home_page", required = false) String homePage,
                                                @RequestPart(name = "download_url", required = false) String downloadUrl,
                                                @RequestPart(name = "platform", required = false) String platform,
                                                @RequestPart(name = "version", required = false) String version,
                                                @RequestPart(name = "description", required = false) String description,
                                                @RequestPart(name = "md5_digest", required = false) String md5Digest,
                                                @RequestPart(name = ":action", required = true) String action,
                                                @RequestPart(name = "name", required = true) String name,
                                                @RequestPart(name = "license", required = false) String license,
                                                @RequestPart(name = "pyversion", required = false) String pyversion,
                                                @RequestPart(name = "summary", required = false) String summary,
                                                @RequestPart(name = "author_email", required = false) String authorEmail,
                                                @RequestPart(name = "content", required = true) MultipartFile file,
                                                HttpServletRequest request); @ApiOperation(value = "This Endpoint will be used for download/install pypi package") @ApiResponses(value = { @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Success"), @ApiResponse(code = HttpURLConnection.HTTP_SEE_OTHER, message = "See Other Location"), @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Request Url Not Found"), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "An error occurred while executing download request."), @ApiResponse(code = HttpURLConnection.HTTP_UNAVAILABLE, message = "Service Unavailable.") }) @PreAuthorize("hasAuthority('ARTIFACTS_RESOLVE')") @RequestMapping(path = "/{storageId}/{repositoryId}/{packageName}", method = RequestMethod.GET) ResponseEntity<String> downloadPackage(@RepositoryMapping Repository repository,
                                                  @PathVariable(name = "packageName") String packageName,
                                                  HttpServletRequest request); @ApiOperation(value = "This Endpoint will be used to retreive pypi artifact/.whl file") @ApiResponses(value = { @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Success"), @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Request Url Not Found"), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "An error occurred while executing download request."), @ApiResponse(code = HttpURLConnection.HTTP_UNAVAILABLE, message = "Service Unavailable.") }) @PreAuthorize("hasAuthority('ARTIFACTS_RESOLVE')") @RequestMapping(path = "/{storageId}/{repositoryId}/packages/{artifactName}", method = RequestMethod.GET) void downloadPackage(@RepositoryMapping Repository repository,
                                @PathVariable(name = "artifactName") String artifactName,
                                HttpServletRequest request,
                                HttpServletResponse response,
                                @RequestHeader HttpHeaders headers); @ApiOperation(value = "This Endpoint will be used to retreive all the versions of packages present in artifactory.") @ApiResponses(value = { @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Success"), @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Request Url Not Found"), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "An error occurred while executing download request."), @ApiResponse(code = HttpURLConnection.HTTP_UNAVAILABLE, message = "Service Unavailable.") }) @PreAuthorize("hasAuthority('ARTIFACTS_RESOLVE')") @RequestMapping(path = "/{storageId}/{repositoryId}/simple/{packageName}", method = RequestMethod.GET, produces = MediaType.TEXT_HTML) ResponseEntity<String> browsePackage(@RepositoryMapping Repository repository,
                                                @PathVariable(name = "packageName") String packageName,
                                                HttpServletRequest request,
                                                HttpServletResponse response,
                                                @RequestHeader HttpHeaders headers);  }
@Test @ExtendWith({ RepositoryManagementTestExecutionListener.class, ArtifactManagementTestExecutionListener.class }) public void testBrowsePackage(@PypiTestRepository(repositoryId = REPOSITORY_RELEASES, storageId = REPOSITORY_STORAGE) Repository repository, @PypiTestArtifact(storageId = REPOSITORY_STORAGE, id = "hello_world_pypi", versions = { "1.0", "2.0", "3.0", "3.1", "3.2", "3.4", "5.1" }) List<Path> packagePaths) { final String storageId = repository.getStorage().getId(); final String repositoryId = repository.getId(); final String url = getContextBaseUrl() + "/storages/{storageId}/{repositoryId}/simple/{packageName}/"; mockMvc.when() .get(url, storageId, repositoryId, "hello_world_pypi") .then() .log() .all() .statusCode(HttpStatus.OK.value()) .contentType(ContentType.HTML) .body(Matchers.containsString("<title>Not Found</title>"), Matchers.containsString("<h1>Not Found</h1>\n"), Matchers.not(Matchers.containsString("<a href="))); packagePaths.stream().forEach(path -> { final String uploadUrl = getContextBaseUrl() + "/storages/{storageId}/{repositoryId}"; mockMvc.contentType(MediaType.MULTIPART_FORM_DATA_VALUE) .multiPart("filetype", "sdist") .multiPart(":action", "file_upload") .multiPart("name", "hello_world_pypi") .multiPart("metadata_version", "1.0") .multiPart("content", path.toFile()) .when() .post(uploadUrl, storageId, repositoryId) .then() .log() .all() .statusCode(HttpStatus.OK.value()) .contentType(ContentType.TEXT) .body(Matchers.containsString("The artifact was deployed successfully.")); }); mockMvc.when() .get(url, storageId, repositoryId, "hello_world_pypi") .then() .log() .all() .statusCode(HttpStatus.OK.value()) .contentType(ContentType.HTML) .body(Matchers.containsString("<title>Links for hello_world_pypi</title>"), Matchers.containsString("<h1>Links for hello_world_pypi</h1>\n"), Matchers.containsString("<a href=")); }