diff --git a/src/www/ui/api/Controllers/LicenseController.php b/src/www/ui/api/Controllers/LicenseController.php index fcc89737ce..0bd5aa0a77 100644 --- a/src/www/ui/api/Controllers/LicenseController.php +++ b/src/www/ui/api/Controllers/LicenseController.php @@ -51,6 +51,7 @@ class LicenseController extends RestController */ private $licenseDao; + /** * @param ContainerInterface $container */ @@ -366,4 +367,31 @@ private function isNewLicense($shortName, $groupId = 0) $statement); return $result["cnt"] == 0; } + + /** + * Handle the upload of a license + * + * @param Request $request + * @param ResponseHelper $response + * @param array $args + * @return ResponseHelper + */ + public function handleImportLicense($request, $response, $args) + { + $reqBody = $this->getParsedBody($request); + $symReq = \Symfony\Component\HttpFoundation\Request::createFromGlobals(); + $adminLicenseFromCsv = $this->restHelper->getPlugin('admin_license_from_csv'); + + $uploadedFile = $symReq->files->get($adminLicenseFromCsv->getFileInputName(), + null); + + $delimiter =$reqBody["delimiter"] ?: ','; + $enclosure = $reqBody["enclosure"] ?: '"'; + + $res = $adminLicenseFromCsv->handleFileUpload($uploadedFile,$delimiter,$enclosure); + + $newInfo = new Info($res[2], $res[1], $res[0] == 200 ? InfoType::INFO : InfoType::ERROR); + + return $response->withJson($newInfo->getArray(), $newInfo->getCode()); + } } diff --git a/src/www/ui/api/documentation/openapi.yaml b/src/www/ui/api/documentation/openapi.yaml index c2434c9aa9..be5ed71f2b 100644 --- a/src/www/ui/api/documentation/openapi.yaml +++ b/src/www/ui/api/documentation/openapi.yaml @@ -1628,6 +1628,46 @@ paths: $ref: '#/components/schemas/Info' default: $ref: '#/components/responses/defaultResponse' + /license/import: + post: + operationId: importLicense + tags: + - License + summary: Import a csv license + description: > + Import a csv license to the database + requestBody: + description: Information about delimiters, inclosure and csv file. + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ImportLicenseRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ImportLicenseRequest' + multipart/form-data: + schema: + type: object + properties: + file_input: + type: string + format: binary + responses: + '400': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/Info' + '200': + description: Successfully imported + content: + application/json: + schema: + $ref: '#/components/schemas/Info' + default: + $ref: '#/components/responses/defaultResponse' /license/{shortname}: parameters: - name: shortname @@ -2098,6 +2138,17 @@ components: example: "path/to/LICENSE" findings: $ref: '#/components/schemas/Findings' + ImportLicenseRequest: + type: array + items: + type: object + properties: + delimiter: + type: string + example: "," + enclosure: + type: string + example: '"' UploadCopyrights: type: array items: diff --git a/src/www/ui/api/index.php b/src/www/ui/api/index.php index d0b32e264c..c37fb20633 100644 --- a/src/www/ui/api/index.php +++ b/src/www/ui/api/index.php @@ -225,6 +225,7 @@ function (\Slim\Routing\RouteCollectorProxy $app) { function (\Slim\Routing\RouteCollectorProxy $app) { $app->get('', LicenseController::class . ':getAllLicenses'); $app->post('', LicenseController::class . ':createLicense'); + $app->post('/import', LicenseController::class . ':handleImportLicense'); $app->get('/{shortname:.+}', LicenseController::class . ':getLicense'); $app->patch('/{shortname:.+}', LicenseController::class . ':updateLicense'); $app->any('/{params:.*}', BadRequestController::class); diff --git a/src/www/ui/page/AdminLicenseFromCSV.php b/src/www/ui/page/AdminLicenseFromCSV.php index 659326fb3f..a582b7beee 100644 --- a/src/www/ui/page/AdminLicenseFromCSV.php +++ b/src/www/ui/page/AdminLicenseFromCSV.php @@ -10,6 +10,8 @@ use Fossology\Lib\Auth\Auth; use Fossology\Lib\Plugin\DefaultPlugin; +use Fossology\UI\Api\Models\Info; +use Fossology\UI\Api\Models\InfoType; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -22,6 +24,7 @@ class AdminLicenseFromCSV extends DefaultPlugin { const NAME = "admin_license_from_csv"; const KEY_UPLOAD_MAX_FILESIZE = 'upload_max_filesize'; + const FILE_INPUT_NAME = 'file_input'; function __construct() { @@ -42,11 +45,11 @@ protected function handle (Request $request) $vars = array(); if ($request->isMethod('POST')) { - $uploadFile = $request->files->get('file_input'); + $uploadFile = $request->files->get(self::FILE_INPUT_NAME); $delimiter = $request->get('delimiter') ?: ','; $enclosure = $request->get('enclosure') ?: '"'; $vars['message'] = $this->handleFileUpload($uploadFile, $delimiter, - $enclosure); + $enclosure)[1]; } $vars[self::KEY_UPLOAD_MAX_FILESIZE] = ini_get(self::KEY_UPLOAD_MAX_FILESIZE); @@ -55,11 +58,12 @@ protected function handle (Request $request) return $this->render("admin_license_from_csv.html.twig", $this->mergeWithDefault($vars)); } + /** * @param UploadedFile $uploadedFile - * @return null|string + * @return array */ - protected function handleFileUpload($uploadedFile,$delimiter=',',$enclosure='"') + public function handleFileUpload($uploadedFile,$delimiter=',',$enclosure='"') { $errMsg = ''; if (! ($uploadedFile instanceof UploadedFile)) { @@ -75,14 +79,23 @@ protected function handleFileUpload($uploadedFile,$delimiter=',',$enclosure='"') $uploadedFile->getClientOriginalName(); } if (! empty($errMsg)) { - return $errMsg; + return array(false, $errMsg,400); } /** @var LicenseCsvImport */ $licenseCsvImport = $this->getObject('app.license_csv_import'); $licenseCsvImport->setDelimiter($delimiter); $licenseCsvImport->setEnclosure($enclosure); - return $licenseCsvImport->handleFile($uploadedFile->getRealPath()); + + return array(true,$licenseCsvImport->handleFile($uploadedFile->getRealPath()),200); + } + + /** + * @return string + */ + public function getFileInputName() + { + return $this::FILE_INPUT_NAME; } } -register_plugin(new AdminLicenseFromCSV()); \ No newline at end of file +register_plugin(new AdminLicenseFromCSV()); diff --git a/src/www/ui_tests/api/Controllers/LicenseControllerTest.php b/src/www/ui_tests/api/Controllers/LicenseControllerTest.php index de2450b8ec..e874b12b9d 100644 --- a/src/www/ui_tests/api/Controllers/LicenseControllerTest.php +++ b/src/www/ui_tests/api/Controllers/LicenseControllerTest.php @@ -90,6 +90,12 @@ class LicenseControllerTest extends \PHPUnit\Framework\TestCase */ private $userDao; + /** + * @var M\MockInterface $adminLicensePlugin + * admin_license_from_csv mock + */ + private $adminLicensePlugin; + /** * @var StreamFactory $streamFactory * Stream factory to create body streams. @@ -111,6 +117,7 @@ protected function setUp() : void $this->restHelper = M::mock(RestHelper::class); $this->licenseDao = M::mock(LicenseDao::class); $this->userDao = M::mock(UserDao::class); + $this->adminLicensePlugin = M::mock('admin_license_from_csv'); $this->dbHelper->shouldReceive('getDbManager')->andReturn($this->dbManager); @@ -119,6 +126,10 @@ protected function setUp() : void $this->restHelper->shouldReceive('getUserId')->andReturn($this->userId); $this->restHelper->shouldReceive('getUserDao')->andReturn($this->userDao); + + $this->restHelper->shouldReceive('getPlugin') + ->withArgs(array('admin_license_from_csv'))->andReturn($this->adminLicensePlugin); + $container->shouldReceive('get')->withArgs(array( 'helper.restHelper'))->andReturn($this->restHelper); $container->shouldReceive('get')->withArgs(array( @@ -785,4 +796,50 @@ public function testUpdateLicenseNonAdmin() $this->assertEquals($this->getResponseJson($expectedResponse), $this->getResponseJson($actualResponse)); } + + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + * @test + * -# Test for LicenseController::handleImportLicense() + * -# Check if response status is 200 + * -# Check if response body is matches the expected response body + */ + public function testImportLicense() + { + + $delimiter = ','; + $enclosure = '"'; + + $body = $this->streamFactory->createStream(json_encode([ + "delimiter" => $delimiter, + "enclosure" => $enclosure + ])); + $FILE_INPUT_NAME = "file_input"; + + $this->adminLicensePlugin->shouldReceive('getFileInputName') + ->andReturn($FILE_INPUT_NAME); + + $res = array(true,"random_message",200); + + $this->adminLicensePlugin->shouldReceive('handleFileUpload')-> withArgs([NULL,$delimiter,$enclosure]) + ->andReturn($res); + + $requestHeaders = new Headers(); + $requestHeaders->setHeader('Content-Type', 'application/json'); + $request = new Request("POST", new Uri("HTTP", "localhost"), + $requestHeaders, [], [], $body); + + $info = new Info(200, "random_message", InfoType::INFO); + $expectedResponse = (new ResponseHelper())->withJson($info->getArray(), + $info->getCode()); + $actualResponse = $this->licenseController->handleImportLicense($request, + new ResponseHelper(), []); + $this->assertEquals($expectedResponse->getStatusCode(), + $actualResponse->getStatusCode()); + $this->assertEquals($this->getResponseJson($expectedResponse), + $this->getResponseJson($actualResponse)); + } + }