/
Chebarik
/
PackageManagement
Обзор
Документация
Войти
/
Chebarik
/
PackageManagement
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/main/java/com/packagemanagement/presentation/controller/PackageController.java
159 строк
6 KB
Николай Мехоношин
Implemented non functional requirements
14 апр 2026, 18:37
14 апр 2026, 18:37
2e86838
Код
Авторство
О чём код?
package com.packagemanagement.presentation.controller; import com.packagemanagement.application.dto.PackageDto; import com.packagemanagement.application.dto.VersionDto; import com.packagemanagement.application.service.PackageApplicationService; import com.packagemanagement.domain.model.PackageFormat; import com.packagemanagement.presentation.annotation.RateLimited; import com.packagemanagement.presentation.request.CreatePackageRequest; import com.packagemanagement.presentation.response.ApiResponse; import com.packagemanagement.presentation.response.PagedResponse; import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; @RestController @RequestMapping("/api/packages") public class PackageController { private static final Logger log = LoggerFactory.getLogger(PackageController.class); private final PackageApplicationService packageService; public PackageController(PackageApplicationService packageService) { this.packageService = packageService; } @RateLimited(capacity = 10, refillRate = 10, periodSeconds = 60) @PostMapping public ResponseEntity<ApiResponse<PackageDto>> createPackage( @Valid @RequestBody CreatePackageRequest request) { log.info("Creating package: {}", request.name()); PackageFormat format = PackageFormat.fromString(request.format()); PackageDto created = packageService.createPackage( request.name(), request.description(), format ); return ResponseEntity .status(HttpStatus.CREATED) .body(ApiResponse.success(created, "Package created successfully")); } @RateLimited(capacity = 5, refillRate = 5, periodSeconds = 60) @PostMapping("/{id}/versions") public ResponseEntity<ApiResponse<VersionDto>> uploadVersion( @PathVariable String id, @RequestParam("versionNumber") String versionNumber, @RequestParam("file") MultipartFile file) throws IOException { log.info("Uploading version {} for package {}", versionNumber, id); if (file.isEmpty()) { return ResponseEntity .badRequest() .body(ApiResponse.error("File is required")); } String originalFilename = file.getOriginalFilename(); VersionDto created = packageService.uploadVersion(id, versionNumber, file.getBytes(), originalFilename); return ResponseEntity .status(HttpStatus.CREATED) .body(ApiResponse.success(created, "Version uploaded successfully")); } @GetMapping public ResponseEntity<ApiResponse<PagedResponse<PackageDto>>> getAllPackages( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "30") int size) { log.debug("Getting all packages, page: {}, size: {}", page, size); List<PackageDto> packages = packageService.getAllPackages(page, size); long totalItems = packageService.getPackageCount(); PagedResponse<PackageDto> pagedResponse = PagedResponse.of(packages, page, size, totalItems); return ResponseEntity.ok(ApiResponse.success(pagedResponse)); } @GetMapping("/search") public ResponseEntity<ApiResponse<List<PackageDto>>> searchPackages( @RequestParam String query) { log.debug("Searching packages with query: {}", query); List<PackageDto> packages = packageService.searchPackages(query); return ResponseEntity.ok(ApiResponse.success(packages)); } @GetMapping("/{id}") public ResponseEntity<ApiResponse<PackageDto>> getPackage(@PathVariable String id) { log.debug("Getting package: {}", id); PackageDto packageDto = packageService.getPackage(id); return ResponseEntity.ok(ApiResponse.success(packageDto)); } @RateLimited(capacity = 30, refillRate = 30, periodSeconds = 60) @GetMapping("/{id}/versions/{version}/download") public ResponseEntity<byte[]> downloadVersion( @PathVariable String id, @PathVariable String version) { log.info("Downloading version {} of package {}", version, id); byte[] content = packageService.downloadVersion(id, version); PackageDto pkg = packageService.getPackage(id); String contentType = "application/octet-stream"; String filename = pkg.name() + "-" + version + ".bin"; try { PackageFormat format = PackageFormat.valueOf(pkg.format()); contentType = format.getContentType(); filename = pkg.name() + "-" + version + "." + format.getExtension(); } catch (Exception e) { log.warn("Unknown format: {}", pkg.format()); } HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType(contentType)); headers.setContentDispositionFormData("attachment", filename); headers.setContentLength(content.length); return new ResponseEntity<>(content, headers, HttpStatus.OK); } @DeleteMapping("/{id}") public ResponseEntity<ApiResponse<Void>> deletePackage(@PathVariable String id) { log.info("Deleting package: {}", id); packageService.deletePackage(id); return ResponseEntity.ok(ApiResponse.success(null, "Package deleted successfully")); } @DeleteMapping("/{id}/versions/{version}") public ResponseEntity<ApiResponse<Void>> deleteVersion( @PathVariable String id, @PathVariable String version) { log.info("Deleting version {} of package {}", version, id); packageService.deleteVersion(id, version); return ResponseEntity.ok(ApiResponse.success(null, "Version deleted successfully")); } }