FOSSology  4.7.0-rc1
Open Source License Compliance by Open Source Software
LicenseController.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2021 HH Partners
4  SPDX-FileCopyrightText: © 2023 Samuel Dushimimana <dushsam100@gmail.com>
5 
6  SPDX-License-Identifier: GPL-2.0-only
7 */
13 namespace Fossology\UI\Api\Controllers;
14 
37 use Psr\Container\ContainerInterface;
38 use Psr\Http\Message\ServerRequestInterface as Request;
39 use Slim\Psr7\Factory\StreamFactory;
40 
46 {
50  const PAGE_PARAM = "page";
54  const LIMIT_PARAM = "limit";
58  const ACTIVE_PARAM = "active";
62  const LICENSE_FETCH_LIMIT = 100;
67  private $licenseDao;
68 
74 
80 
81 
85  public function __construct($container)
86  {
87  parent::__construct($container);
88  $this->licenseDao = $this->container->get('dao.license');
89  $this->adminLicenseAckDao = $this->container->get('dao.license.acknowledgement');
90  $this->licenseStdCommentDao = $this->container->get('dao.license.stdc');
91  }
92 
102  public function getLicense($request, $response, $args)
103  {
104  $shortName = $args["shortname"];
105 
106  if (empty($shortName)) {
107  throw new HttpBadRequestException("Short name missing from request.");
108  }
109 
110  $license = $this->licenseDao->getLicenseByShortName($shortName,
111  $this->restHelper->getGroupId());
112 
113  if ($license === null) {
114  throw new HttpNotFoundException(
115  "No license found with short name '$shortName'.");
116  }
117 
118  $obligations = $this->licenseDao->getLicenseObligations([$license->getId()],
119  false);
120  $obligations = array_merge($obligations,
121  $this->licenseDao->getLicenseObligations([$license->getId()], true));
122  $obligationList = [];
123  foreach ($obligations as $obligation) {
124  $obligationList[] = new Obligation(
125  $obligation['ob_pk'],
126  $obligation['ob_topic'],
127  $obligation['ob_type'],
128  $obligation['ob_text'],
129  $obligation['ob_classification'],
130  $obligation['ob_comment']
131  );
132  }
133 
134  $returnVal = new License(
135  $license->getId(),
136  $license->getShortName(),
137  $license->getFullName(),
138  $license->getText(),
139  $license->getUrl(),
140  $obligationList,
141  $license->getRisk()
142  );
143 
144  return $response->withJson($returnVal->getArray(), 200);
145  }
146 
156  public function getAllLicenses($request, $response, $args)
157  {
158  $apiVersion = ApiVersion::getVersion($request);
159  $query = $request->getQueryParams();
160  if ($apiVersion == ApiVersion::V2) {
161  $page = $query[self::PAGE_PARAM] ?? "";
162  $limit = $query[self::LIMIT_PARAM] ?? "";
163  $onlyActive = $query[self::ACTIVE_PARAM] ?? "";
164  } else {
165  $page = $request->getHeaderLine(self::PAGE_PARAM);
166  $limit = $request->getHeaderLine(self::LIMIT_PARAM);
167  $onlyActive = $request->getHeaderLine(self::ACTIVE_PARAM);
168  }
169  if (! empty($limit)) {
170  $limit = filter_var($limit, FILTER_VALIDATE_INT);
171  if ($limit < 1) {
172  throw new HttpBadRequestException(
173  "limit should be positive integer > 1");
174  }
175  } else {
176  $limit = self::LICENSE_FETCH_LIMIT;
177  }
178 
179  $kind = "all";
180  if (array_key_exists("kind", $query) && !empty($query["kind"]) &&
181  in_array($query["kind"], ["all", "candidate", "main"])) {
182  $kind = $query["kind"];
183  }
184 
185  $totalPages = $this->dbHelper->getLicenseCount($kind,
186  $this->restHelper->getGroupId());
187  $totalPages = intval(ceil($totalPages / $limit));
188 
189  if (! empty($page) || $page == "0") {
190  $page = filter_var($page, FILTER_VALIDATE_INT);
191  if ($page <= 0) {
192  throw new HttpBadRequestException(
193  "page should be positive integer > 0");
194  }
195  if ($totalPages != 0 && $page > $totalPages) {
196  throw (new HttpBadRequestException(
197  "Can not exceed total pages: $totalPages"))
198  ->setHeaders(["X-Total-Pages" => $totalPages]);
199  }
200  } else {
201  $page = 1;
202  }
203  if (! empty($onlyActive)) {
204  $onlyActive = filter_var($onlyActive, FILTER_VALIDATE_BOOLEAN);
205  } else {
206  $onlyActive = false;
207  }
208 
209  $licenses = $this->dbHelper->getLicensesPaginated($page, $limit,
210  $kind, $this->restHelper->getGroupId(), $onlyActive);
211  $licenseList = [];
212 
213  foreach ($licenses as $license) {
214  $newRow = new License(
215  $license['rf_pk'],
216  $license['rf_shortname'],
217  $license['rf_fullname'],
218  $license['rf_text'],
219  $license['rf_url'],
220  null,
221  $license['rf_risk'],
222  $license['group_fk'] != 0
223  );
224  $licenseList[] = $newRow->getArray();
225  }
226 
227  return $response->withHeader("X-Total-Pages", $totalPages)
228  ->withJson($licenseList, 200);
229  }
230 
240  public function createLicense($request, $response, $args)
241  {
242  $newLicense = $this->getParsedBody($request);
243  $newLicense = License::parseFromArray($newLicense);
244  if ($newLicense === -1) {
245  throw new HttpBadRequestException(
246  "Input contains additional properties.");
247  }
248  if ($newLicense === -2) {
249  throw new HttpBadRequestException("Property 'shortName' is required.");
250  }
251  if (! $newLicense->getIsCandidate() && ! Auth::isAdmin()) {
252  throw new HttpForbiddenException("Need to be admin to create " .
253  "non-candidate license.");
254  }
255  $tableName = "license_ref";
256  $assocData = [
257  "rf_shortname" => $newLicense->getShortName(),
258  "rf_fullname" => $newLicense->getFullName(),
259  "rf_text" => $newLicense->getText(),
260  "rf_md5" => md5($newLicense->getText()),
261  "rf_risk" => $newLicense->getRisk(),
262  "rf_url" => $newLicense->getUrl(),
263  "rf_detector_type" => 1
264  ];
265  $okToAdd = true;
266  if ($newLicense->getIsCandidate()) {
267  $tableName = "license_candidate";
268  $assocData["group_fk"] = $this->restHelper->getGroupId();
269  $assocData["rf_user_fk_created"] = $this->restHelper->getUserId();
270  $assocData["rf_user_fk_modified"] = $this->restHelper->getUserId();
271  $assocData["marydone"] = $newLicense->getMergeRequest();
272  $okToAdd = $this->isNewLicense($newLicense->getShortName(),
273  $this->restHelper->getGroupId());
274  } else {
275  $okToAdd = $this->isNewLicense($newLicense->getShortName());
276  }
277  if (! $okToAdd) {
278  throw new HttpConflictException("License with shortname '" .
279  $newLicense->getShortName() . "' already exists!");
280  }
281  try {
282  $rfPk = $this->dbHelper->getDbManager()->insertTableRow($tableName,
283  $assocData, __METHOD__ . ".newLicense", "rf_pk");
284  $newInfo = new Info(201, $rfPk, InfoType::INFO);
285  } catch (\Exception $e) {
286  throw new HttpConflictException(
287  "License with same text already exists!", $e);
288  }
289  return $response->withJson($newInfo->getArray(), $newInfo->getCode());
290  }
291 
301  public function updateLicense($request, $response, $args)
302  {
303  $newParams = $this->getParsedBody($request);
304  $shortName = $args["shortname"];
305  if (empty($shortName)) {
306  throw new HttpBadRequestException("Short name missing from request.");
307  }
308 
309  $license = $this->licenseDao->getLicenseByShortName($shortName,
310  $this->restHelper->getGroupId());
311 
312  if ($license === null) {
313  throw new HttpNotFoundException(
314  "No license found with short name '$shortName'.");
315  }
316  $isCandidate = $this->restHelper->getDbHelper()->doesIdExist(
317  "license_candidate", "rf_pk", $license->getId());
318  if (!$isCandidate && !Auth::isAdmin()) {
319  throw new HttpForbiddenException(
320  "Need to be admin to edit non-candidate license.");
321  }
322  if ($isCandidate && ! $this->restHelper->getUserDao()->isAdvisorOrAdmin(
323  $this->restHelper->getUserId(), $this->restHelper->getGroupId())) {
324  throw new HttpForbiddenException(
325  "Operation not permitted for this group.");
326  }
327 
328  $assocData = [];
329  if (array_key_exists('fullName', $newParams)) {
330  $assocData['rf_fullname'] = StringOperation::replaceUnicodeControlChar($newParams['fullName']);
331  }
332  if (array_key_exists('text', $newParams)) {
333  $assocData['rf_text'] = StringOperation::replaceUnicodeControlChar($newParams['text']);
334  }
335  if (array_key_exists('url', $newParams)) {
336  $assocData['rf_url'] = StringOperation::replaceUnicodeControlChar($newParams['url']);
337  }
338  if (array_key_exists('risk', $newParams)) {
339  $assocData['rf_risk'] = intval($newParams['risk']);
340  }
341  if (empty($assocData)) {
342  throw new HttpBadRequestException("Empty body sent.");
343  }
344 
345  $tableName = "license_ref";
346  if ($isCandidate) {
347  $tableName = "license_candidate";
348  }
349  $this->dbHelper->getDbManager()->updateTableRow($tableName, $assocData,
350  "rf_pk", $license->getId(), __METHOD__ . ".updateLicense");
351  $newInfo = new Info(200, "License " . $license->getShortName() .
352  " updated.", InfoType::INFO);
353  return $response->withJson($newInfo->getArray(), $newInfo->getCode());
354  }
355 
362  private function isNewLicense($shortName, $groupId = 0)
363  {
364  $tableName = "ONLY license_ref";
365  $where = "";
366  $params = [$shortName];
367  $statement = __METHOD__;
368  if ($groupId != 0) {
369  $tableName = "license_candidate";
370  $where = "AND group_fk = $2";
371  $params[] = $groupId;
372  $statement .= ".candidate";
373  }
374  $sql = "SELECT count(*) cnt FROM " .
375  "$tableName WHERE rf_shortname = $1 $where;";
376  $result = $this->dbHelper->getDbManager()->getSingleRow($sql, $params,
377  $statement);
378  return $result["cnt"] == 0;
379  }
380 
390  public function handleImportLicense($request, $response, $args)
391  {
392  $apiVersion = ApiVersion::getVersion($request);
393  $this->throwNotAdminException();
394  $symReq = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
396  $adminLicenseFromCsv = $this->restHelper->getPlugin('admin_license_from_csv');
397 
398  $uploadedFile = $symReq->files->get($adminLicenseFromCsv->getFileInputName($apiVersion),
399  null);
400 
401  $requestBody = $this->getParsedBody($request);
402  $delimiter = ',';
403  $enclosure = '"';
404  if (array_key_exists("delimiter", $requestBody) && !empty($requestBody["delimiter"])) {
405  $delimiter = $requestBody["delimiter"];
406  }
407  if (array_key_exists("enclosure", $requestBody) && !empty($requestBody["enclosure"])) {
408  $enclosure = $requestBody["enclosure"];
409  }
410 
411  $res = $adminLicenseFromCsv->handleFileUpload($uploadedFile, $delimiter,
412  $enclosure);
413 
414  if (!$res[0]) {
415  throw new HttpBadRequestException($res[1]);
416  }
417 
418  $newInfo = new Info($res[2], $res[1], InfoType::INFO);
419  return $response->withJson($newInfo->getArray(), $newInfo->getCode());
420  }
421 
431  public function getCandidates($request, $response, $args)
432  {
433  $apiVersion = ApiVersion::getVersion($request);
434  $this->throwNotAdminException();
436  $adminLicenseCandidate = $this->restHelper->getPlugin("admin_license_candidate");
437  $licenses = LicenseCandidate::convertDbArray($adminLicenseCandidate->getCandidateArrayData(), $apiVersion);
438  return $response->withJson($licenses, 200);
439  }
440 
450  public function deleteAdminLicenseCandidate($request, $response, $args)
451  {
452  $this->throwNotAdminException();
453  $id = intval($args['id']);
455  $adminLicenseCandidate = $this->restHelper->getPlugin('admin_license_candidate');
456 
457  if (!$adminLicenseCandidate->getDataRow($id)) {
458  throw new HttpNotFoundException("License candidate not found.");
459  }
460  $res = $adminLicenseCandidate->doDeleteCandidate($id,false);
461  $message = $res->getContent();
462  if ($res->getContent() !== 'true') {
463  throw new HttpConflictException(
464  "License used at following locations, can not delete: " .
465  $message);
466  }
467  $resInfo = new Info(202, "License candidate will be deleted.",
468  InfoType::INFO);
469  return $response->withJson($resInfo->getArray(), $resInfo->getCode());
470  }
471 
481  public function getAllAdminAcknowledgements($request, $response, $args)
482  {
483  $apiVersion = ApiVersion::getVersion($request);
484  $this->throwNotAdminException();
485  $rawData = $this->adminLicenseAckDao->getAllAcknowledgements();
486 
487  $acknowledgements = [];
488  foreach ($rawData as $ack) {
489  $acknowledgements[] = new AdminAcknowledgement(intval($ack['la_pk']), $ack['name'], $ack['acknowledgement'], $ack['is_enabled'] == "t");
490  }
491 
492  $res = array_map(fn($acknowledgement) => $acknowledgement->getArray($apiVersion), $acknowledgements);
493  return $response->withJson($res, 200);
494  }
495 
505  public function handleAdminLicenseAcknowledgement($request, $response, $args)
506  {
507  $body = $this->getParsedBody($request);
508  $errors = [];
509  $success = [];
510 
511  if (empty($body)) {
512  throw new HttpBadRequestException("Request body is missing or empty.");
513  }
514  if (!is_array($body)) {
515  throw new HttpBadRequestException("Request body should be an array.");
516  }
517  foreach (array_keys($body) as $index) {
518  $ackReq = $body[$index];
519  if ((!$ackReq['update'] && empty($ackReq['name'])) || ($ackReq['update'] && empty($ackReq['name']) && !$ackReq['toggle'])) {
520  $error = new Info(400, "Acknowledgement name missing from the request #" . ($index + 1), InfoType::ERROR);
521  $errors[] = $error->getArray();
522  continue;
523  } else if ((!$ackReq['update'] && empty($ackReq['ack'])) || ($ackReq['update'] && empty($ackReq['ack']) && !$ackReq['toggle'])) {
524  $error = new Info(400, "Acknowledgement text missing from the request #" . ($index + 1), InfoType::ERROR);
525  $errors[] = $error->getArray();
526  continue;
527  }
528 
529  if ($ackReq['update']) {
530 
531  if (empty($ackReq['id'])) {
532  $error = new Info(400, "Acknowledgement ID missing from the request #" . ($index + 1), InfoType::ERROR);
533  $errors[] = $error->getArray();
534  continue;
535  }
536 
537  $sql = "SELECT la_pk, name FROM license_std_acknowledgement WHERE la_pk = $1;";
538  $existingAck = $this->dbHelper->getDbManager()->getSingleRow($sql, [$ackReq['id']]);
539 
540  if (empty($existingAck)) {
541  $error = new Info(404, "Acknowledgement not found for the request #" . ($index + 1), InfoType::ERROR);
542  $errors[] = $error->getArray();
543  continue;
544  } else if ($existingAck["name"] != $ackReq["name"] && $this->dbHelper->doesIdExist("license_std_acknowledgement", "name", $ackReq["name"])) {
545  $error = new Info(400, "Name already exists.", InfoType::ERROR);
546  $errors[] = $error->getArray();
547  continue;
548  }
549 
550  if ($ackReq["name"] && $ackReq["ack"]) {
551  $this->adminLicenseAckDao->updateAcknowledgement($ackReq["id"], $ackReq["name"], $ackReq["ack"]);
552  }
553 
554  if ($ackReq["toggle"]) {
555  $this->adminLicenseAckDao->toggleAcknowledgement($ackReq["id"]);
556  }
557 
558  $info = new Info(200, "Successfully updated admin license acknowledgement with name '" . $existingAck["name"] . "'", InfoType::INFO);
559  } else {
560 
561  if ($this->dbHelper->doesIdExist("license_std_acknowledgement", "name", $ackReq["name"])) {
562  $error = new Info(400, "Name already exists for the request #" . ($index + 1), InfoType::ERROR);
563  $errors[] = $error->getArray();
564  continue;
565  }
566  $res = $this->adminLicenseAckDao->insertAcknowledgement($ackReq["name"], $ackReq["ack"]);
567  if ($res == -2) {
568  $error = new Info(500, "Error while inserting new acknowledgement.", InfoType::ERROR);
569  $errors[] = $error->getArray();
570  continue;
571  }
572  $info = new Info(201, "Acknowledgement added successfully.", InfoType::INFO);
573  }
574  $success[] = $info->getArray();
575  }
576  return $response->withJson([
577  'success' => $success,
578  'errors' => $errors
579  ], 200);
580  }
581 
590  public function getAllLicenseStandardComments($request, $response, $args)
591  {
592  $apiVersion = ApiVersion::getVersion($request);
593  $rawData = $this->licenseStdCommentDao->getAllComments();
594  $comments = [];
595  foreach ($rawData as $cmt) {
596  $comments[] = new LicenseStandardComment(intval($cmt['lsc_pk']), $cmt['name'], $cmt['comment'], $cmt['is_enabled'] == "t");
597  }
598  $res = array_map(fn($comment) => $comment->getArray($apiVersion), $comments);
599  return $response->withJson($res, 200);
600  }
601 
611  public function handleLicenseStandardComment($request, $response, $args)
612  {
613  $this->throwNotAdminException();
614 
615  $body = $this->getParsedBody($request);
616  $errors = [];
617  $success = [];
618 
619  if (empty($body)) {
620  throw new HttpBadRequestException("Request body is missing or empty.");
621  }
622  if (!is_array($body)) {
623  throw new HttpBadRequestException("Request body should be an array.");
624  }
625  foreach (array_keys($body) as $index) {
626  $commentReq = $body[$index];
627 
628  // Check if name and comment are present if update is false
629  if ((!$commentReq['update'] && empty($commentReq['name']))) {
630  $error = new Info(400, "Comment name missing from the request #" . ($index + 1), InfoType::ERROR);
631  $errors[] = $error->getArray();
632  continue;
633  } else if ((!$commentReq['update'] && empty($commentReq['comment']))) {
634  $error = new Info(400, "Comment text missing from the request #" . ($index + 1), InfoType::ERROR);
635  $errors[] = $error->getArray();
636  continue;
637  } else if ($commentReq['update'] && empty($commentReq['name']) && empty($commentReq['comment']) && empty($commentReq['toggle'])) {
638  $error = new Info(400, "Comment name, text or toggle missing from the request #" . ($index + 1), InfoType::ERROR);
639  $errors[] = $error->getArray();
640  continue;
641  }
642 
643  if ($commentReq['update']) {
644 
645  if (empty($commentReq['id'])) {
646  $error = new Info(400, "Standard Comment ID missing from the request #" . ($index + 1), InfoType::ERROR);
647  $errors[] = $error->getArray();
648  continue;
649  }
650 
651  $sql = "SELECT lsc_pk, name, comment FROM license_std_comment WHERE lsc_pk = $1;";
652  $existingComment = $this->dbHelper->getDbManager()->getSingleRow($sql, [$commentReq['id']]);
653 
654  if (empty($existingComment)) {
655  $error = new Info(404, "Standard comment not found for the request #" . ($index + 1), InfoType::ERROR);
656  $errors[] = $error->getArray();
657  continue;
658  // check if the new name doesn't already exist
659  } else if ($existingComment["name"] != $commentReq["name"] && $this->dbHelper->doesIdExist("license_std_comment", "name", $commentReq["name"])) {
660  $error = new Info(400, "Name already exists.", InfoType::ERROR);
661  $errors[] = $error->getArray();
662  continue;
663  }
664 
665  // if both fields were specified and are not empty, update the comment
666  if ($commentReq["name"] && $commentReq["comment"]) {
667  $this->licenseStdCommentDao->updateComment($commentReq["id"], $commentReq["name"], $commentReq["comment"]);
668  } else if ($commentReq["name"]) {
669  $this->licenseStdCommentDao->updateComment($commentReq["id"], $commentReq["name"], $existingComment["comment"]);
670  } else if ($commentReq["comment"]) {
671  $this->licenseStdCommentDao->updateComment($commentReq["id"], $existingComment["name"], $commentReq["comment"]);
672  }
673  // toggle the comment if the toggle field is set to true
674  if ($commentReq["toggle"]) {
675  $this->licenseStdCommentDao->toggleComment($commentReq["id"]);
676  }
677 
678  $info = new Info(200, "Successfully updated standard comment", InfoType::INFO);
679  } else {
680 
681  if ($this->dbHelper->doesIdExist("license_std_comment", "name", $commentReq["name"])) {
682  $error = new Info(400, "Name already exists for the request #" . ($index + 1), InfoType::ERROR);
683  $errors[] = $error->getArray();
684  continue;
685  }
686  $res = $this->licenseStdCommentDao->insertComment($commentReq["name"], $commentReq["comment"]);
687  if ($res == -2) {
688  $error = new Info(500, "Error while inserting new comment.", InfoType::ERROR);
689  $errors[] = $error->getArray();
690  continue;
691  }
692  $info = new Info(201, "Comment with name '". $commentReq['name'] ."' added successfully.", InfoType::INFO);
693  }
694  $success[] = $info->getArray();
695  }
696  return $response->withJson([
697  'success' => $success,
698  'errors' => $errors
699  ], 200);
700  }
701 
711  public function verifyLicense($request, $response, $args)
712  {
713  $this->throwNotAdminException();
714  $licenseShortName = $args["shortname"];
715  $body = $this->getParsedBody($request);
716  $parentName = $body["parentShortname"];
717 
718  if (empty($licenseShortName) || empty($parentName)) {
719  throw new HttpBadRequestException(
720  "License ShortName or Parent ShortName is missing.");
721  }
722 
723  $license = $this->licenseDao->getLicenseByShortName($licenseShortName, $this->restHelper->getGroupId());
724  if ($licenseShortName != $parentName) {
725  $parentLicense = $this->licenseDao->getLicenseByShortName($parentName, $this->restHelper->getGroupId());
726  } else {
727  $parentLicense = $license;
728  }
729 
730  if (empty($license) || empty($parentLicense)) {
731  throw new HttpNotFoundException("License not found.");
732  }
733 
734  try {
736  $adminLicenseCandidate = $this->restHelper->getPlugin('admin_license_candidate');
737  $ok = $adminLicenseCandidate->verifyCandidate($license->getId(), $licenseShortName, $parentLicense->getId());
738  } catch (\Throwable $th) {
739  throw new HttpConflictException('The license text already exists.', $th);
740  }
741 
742  if (!$ok) {
743  throw new HttpBadRequestException('Short name must be unique');
744  }
745  $with = $parentLicense->getId() === $license->getId() ? '' : " as variant of ($parentName).";
746  $info = new Info(200, 'Successfully verified candidate ('.$licenseShortName.')'.$with, InfoType::INFO);
747  return $response->withJson($info->getArray(), $info->getCode());
748  }
749 
759  public function mergeLicense($request, $response, $args)
760  {
761  $this->throwNotAdminException();
762  $licenseShortName = $args["shortname"];
763  $body = $this->getParsedBody($request);
764  $parentName = $body["parentShortname"];
765 
766  if (empty($licenseShortName) || empty($parentName)) {
767  throw new HttpBadRequestException(
768  "License ShortName or Parent ShortName is missing.");
769  }
770  if ($licenseShortName == $parentName) {
771  throw new HttpBadRequestException(
772  "License ShortName and Parent ShortName are same.");
773  }
774 
775  $license = $this->licenseDao->getLicenseByShortName($licenseShortName, $this->restHelper->getGroupId());
776  $mergeLicense = $this->licenseDao->getLicenseByShortName($parentName, $this->restHelper->getGroupId());
777 
778  if (empty($license) || empty($mergeLicense)) {
779  throw new HttpNotFoundException("License not found.");
780  }
781 
783  $adminLicenseCandidate = $this->restHelper->getPlugin('admin_license_candidate');
784  $vars = $adminLicenseCandidate->getDataRow($license->getId());
785  if (empty($vars)) {
786  throw new HttpNotFoundException("Candidate license not found.");
787  }
788 
789  try {
790  $vars['shortname'] = $vars['rf_shortname'];
791  $ok = $adminLicenseCandidate->mergeCandidate($license->getId(), $mergeLicense->getId(), $vars);
792  } catch (\Throwable $th) {
793  throw new HttpConflictException('The license text already exists.', $th);
794  }
795 
796  if (!$ok) {
797  throw new HttpInternalServerErrorException("Please try again later.");
798  }
799  $info = new Info(200, "Successfully merged candidate ($parentName) into ($licenseShortName).", InfoType::INFO);
800  return $response->withJson($info->getArray(), $info->getCode());
801  }
802 
812  public function getSuggestedLicense($request, $response, $args)
813  {
814  $this->throwNotAdminException();
815  $body = $this->getParsedBody($request);
816  $rfText = $body["referenceText"];
817  if (empty($rfText)) {
818  throw new HttpBadRequestException("Reference text is missing.");
819  }
821  $adminLicenseCandidate = $this->restHelper->getPlugin('admin_license_candidate');
822  list ($suggestIds, $rendered) = $adminLicenseCandidate->suggestLicenseId($rfText, true);
823  $highlights = [];
824 
825  foreach ($rendered as $value) {
826  $highlights[] = $value->getArray();
827  }
828 
829  if (! empty($suggestIds)) {
830  $suggest = $suggestIds[0];
831  $suggestLicense = $adminLicenseCandidate->getDataRow($suggest, 'ONLY license_ref');
832  $suggestLicense = [
833  'id' => intval($suggestLicense['rf_pk']),
834  'spdxName' => $suggestLicense['rf_spdx_id'],
835  'shortName' => $suggestLicense['rf_shortname'],
836  'fullName' => $suggestLicense['rf_fullname'],
837  'text' => $suggestLicense['rf_text'],
838  'url' => $suggestLicense['rf_url'],
839  'notes' => $suggestLicense['rf_notes'],
840  'risk' => intval($suggestLicense['rf_risk']),
841  'highlights' => $highlights,
842  ];
843  }
844  if (empty($suggestLicense)) {
845  $suggestLicense = [];
846  }
847  return $response->withJson($suggestLicense, 200);
848  }
849 
859  public function exportAdminLicenseToCSV($request, $response, $args)
860  {
861  $this->throwNotAdminException();
862  $query = $request->getQueryParams();
863  $rf = 0;
864  if (array_key_exists('id', $query)) {
865  $rf = intval($query['id']);
866  }
867  if ($rf != 0 &&
868  (! $this->dbHelper->doesIdExist("license_ref", "rf_pk", $rf) &&
869  ! $this->dbHelper->doesIdExist("license_candidate", "rf_pk", $rf))) {
870  throw new HttpNotFoundException("License not found.");
871  }
872  $dbManager = $this->dbHelper->getDbManager();
873  $licenseCsvExport = new LicenseCsvExport($dbManager);
874  $content = $licenseCsvExport->createCsv($rf);
875  $fileName = "fossology-license-export-" . date("YMj-Gis");
876  $newResponse = $response->withHeader('Content-type', 'text/csv, charset=UTF-8')
877  ->withHeader('Content-Disposition', 'attachment; filename=' . $fileName . '.csv')
878  ->withHeader('Pragma', 'no-cache')
879  ->withHeader('Cache-Control', 'no-cache, must-revalidate, maxage=1, post-check=0, pre-check=0')
880  ->withHeader('Expires', 'Expires: Thu, 19 Nov 1981 08:52:00 GMT');
881  $sf = new StreamFactory();
882  return $newResponse->withBody(
883  $content ? $sf->createStream($content) : $sf->createStream('')
884  );
885  }
886 
896  public function exportAdminLicenseToJSON($request, $response, $args)
897  {
898  $this->throwNotAdminException();
899  $query = $request->getQueryParams();
900  $rf = 0;
901  if (array_key_exists('id', $query)) {
902  $rf = intval($query['id']);
903  }
904  if ($rf != 0 &&
905  (! $this->dbHelper->doesIdExist("license_ref", "rf_pk", $rf) &&
906  ! $this->dbHelper->doesIdExist("license_candidate", "rf_pk", $rf))) {
907  throw new HttpNotFoundException("License not found.");
908  }
909  $dbManager = $this->dbHelper->getDbManager();
910  $licenseCsvExport = new LicenseCsvExport($dbManager);
911  $content = $licenseCsvExport->createCsv($rf, false, true);
912  $fileName = "fossology-license-export-" . date("YMj-Gis");
913  $newResponse = $response->withHeader('Content-type', 'text/json, charset=UTF-8')
914  ->withHeader('Content-Disposition', 'attachment; filename=' . $fileName . '.json')
915  ->withHeader('Pragma', 'no-cache')
916  ->withHeader('Cache-Control', 'no-cache, must-revalidate, maxage=1, post-check=0, pre-check=0')
917  ->withHeader('Expires', 'Expires: Thu, 19 Nov 1981 08:52:00 GMT');
918  $sf = new StreamFactory();
919  return $newResponse->withBody(
920  $content ? $sf->createStream($content) : $sf->createStream('')
921  );
922  }
923 
941  public function exportBulkText($request, $response, $args)
942  {
943  $this->throwNotAdminException();
944  $query = $request->getQueryParams();
945 
946  $format = 'json';
947  if (array_key_exists('format', $query) && !empty($query['format'])) {
948  $format = strtolower($query['format']);
949  }
950  if (!in_array($format, array('csv', 'json'))) {
951  throw new HttpBadRequestException("Invalid format. Use 'csv' or 'json'.");
952  }
953 
954  $filter = 'all';
955  if (array_key_exists('filter', $query) && !empty($query['filter'])) {
956  $filter = strtolower($query['filter']);
957  }
958  if (!in_array($filter, array('all', 'user', 'group'))) {
959  throw new HttpBadRequestException("Invalid filter. Use 'all', 'user', or 'group'.");
960  }
961 
962  $userPk = 0;
963  $groupPk = 0;
964  if ($filter === 'user') {
965  if (!array_key_exists('userId', $query)) {
966  throw new HttpBadRequestException("userId is required when filter=user.");
967  }
968  $userPk = intval($query['userId']);
969  if ($userPk <= 0) {
970  throw new HttpBadRequestException("Invalid userId.");
971  }
972  } elseif ($filter === 'group') {
973  if (!array_key_exists('groupId', $query)) {
974  throw new HttpBadRequestException("groupId is required when filter=group.");
975  }
976  $groupPk = intval($query['groupId']);
977  if ($groupPk <= 0) {
978  throw new HttpBadRequestException("Invalid groupId.");
979  }
980  }
981 
982  $dbManager = $this->dbHelper->getDbManager();
983  $bulkTextExport = new BulkTextExport($dbManager);
984 
985  $isJson = ($format === 'json');
986  if (!$isJson) {
987  $delimiter = ',';
988  if (array_key_exists('delimiter', $query) && !empty($query['delimiter'])) {
989  $delimiter = $query['delimiter'];
990  }
991 
992  $enclosure = '"';
993  if (array_key_exists('enclosure', $query) && !empty($query['enclosure'])) {
994  $enclosure = $query['enclosure'];
995  }
996 
997  try {
998  $bulkTextExport->setDelimiter($delimiter);
999  $bulkTextExport->setEnclosure($enclosure);
1000  } catch (\InvalidArgumentException $e) {
1001  throw new HttpBadRequestException($e->getMessage());
1002  }
1003  }
1004 
1005  $content = $bulkTextExport->exportBulkText($userPk, $groupPk, $isJson);
1006  $fileName = "fossology-bulk-text-export-" . date("YMj-Gis");
1007  $extension = $isJson ? 'json' : 'csv';
1008  $contentType = $isJson ? 'application/json; charset=UTF-8' : 'text/csv; charset=UTF-8';
1009 
1010  $newResponse = $response->withHeader('Content-type', $contentType)
1011  ->withHeader('Content-Disposition', 'attachment; filename=' . $fileName . '.' . $extension)
1012  ->withHeader('Pragma', 'no-cache')
1013  ->withHeader('Cache-Control', 'no-cache, must-revalidate, maxage=1, post-check=0, pre-check=0')
1014  ->withHeader('Expires', 'Expires: Thu, 19 Nov 1981 08:52:00 GMT');
1015 
1016  $sf = new StreamFactory();
1017  return $newResponse->withBody(
1018  $content ? $sf->createStream($content) : $sf->createStream('')
1019  );
1020  }
1021 }
Helper class to export license reference bulk data as CSV or JSON from the DB.
Helper class to export license list as a CSV from the DB.
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
static isAdmin()
Check if user is admin.
Definition: Auth.php:92
Fossology exception.
Definition: Exception.php:15
static replaceUnicodeControlChar($input, $replace="")
handleLicenseStandardComment($request, $response, $args)
handleAdminLicenseAcknowledgement($request, $response, $args)
exportAdminLicenseToJSON($request, $response, $args)
getAllLicenseStandardComments($request, $response, $args)
getAllAdminAcknowledgements($request, $response, $args)
Base controller for REST calls.
getParsedBody(ServerRequestInterface $request)
Parse request body as JSON and return associative PHP array.
Override Slim response for withJson function.
static getVersion(ServerRequestInterface $request)
Definition: ApiVersion.php:29
Different type of infos provided by REST.
Definition: InfoType.php:16
Info model to contain general error and return values.
Definition: Info.php:19
static convertDbArray($rows, $version=ApiVersion::V1)
static parseFromArray($inputLicense)
Definition: License.php:342