FOSSology  4.7.1
Open Source License Compliance by Open Source Software
UploadController.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2018, 2020 Siemens AG
4  SPDX-FileContributor: Gaurav Mishra <mishra.gaurav@siemens.com>
5  SPDX-FileCopyrightText: © 2022 Soham Banerjee <sohambanerjee4abc@hotmail.com>
6  SPDX-FileCopyrightText: © 2022, 2023 Samuel Dushimimana <dushsam100@gmail.com>
7  SPDX-FileContributor: Kaushlendra Pratap <kaushlendra-pratap.singh@siemens.com>
8 
9  SPDX-License-Identifier: GPL-2.0-only
10 */
11 
17 namespace Fossology\UI\Api\Controllers;
18 
51 use Psr\Http\Message\ServerRequestInterface;
52 use Slim\Psr7\Factory\StreamFactory;
53 
59 {
60 
64  const AGENT_PARAM = "agent";
65 
69  const FOLDER_PARAM = "folderId";
70 
74  const RECURSIVE_PARAM = "recursive";
75 
79  const FILTER_NAME = "name";
80 
84  const FILTER_STATUS = "status";
85 
89  const FILTER_ASSIGNEE = "assignee";
90 
94  const FILTER_DATE = "since";
95 
99  const PAGE_PARAM = "page";
100 
104  const LIMIT_PARAM = "limit";
105 
109  const UPLOAD_FETCH_LIMIT = 100;
110 
114  const CONTAINER_PARAM = "containers";
115 
119  const VALID_STATUS = ["open", "inprogress", "closed", "rejected"];
120 
124  private $agentNames = AgentRef::AGENT_LIST;
125 
130  private $agentDao;
131 
132  public function __construct($container)
133  {
134  parent::__construct($container);
135  $groupId = $this->restHelper->getGroupId();
136  $dbManager = $this->dbHelper->getDbManager();
137  $this->agentDao = $this->container->get('dao.agent');
138  $uploadBrowseProxy = new UploadBrowseProxy($groupId, 0, $dbManager, false);
139  $uploadBrowseProxy->sanity();
140  }
141 
151  public function getUploads($request, $response, $args)
152  {
153  $id = null;
154  $folderId = null;
155  $recursive = true;
156  $query = $request->getQueryParams();
157  $name = null;
158  $status = null;
159  $assignee = null;
160  $since = null;
161  $apiVersion = ApiVersion::getVersion($request);
162 
163  if (array_key_exists(self::FOLDER_PARAM, $query)) {
164  $folderId = filter_var($query[self::FOLDER_PARAM], FILTER_VALIDATE_INT);
165  if (! $this->restHelper->getFolderDao()->isFolderAccessible($folderId,
166  $this->restHelper->getUserId())) {
167  throw new HttpNotFoundException("Folder does not exist");
168  }
169  }
170 
171  if (array_key_exists(self::RECURSIVE_PARAM, $query)) {
172  $recursive = filter_var($query[self::RECURSIVE_PARAM],
173  FILTER_VALIDATE_BOOLEAN);
174  }
175  if (array_key_exists(self::FILTER_NAME, $query)) {
176  $name = $query[self::FILTER_NAME];
177  }
178  if (array_key_exists(self::FILTER_STATUS, $query)) {
179  switch (strtolower($query[self::FILTER_STATUS])) {
180  case "open":
181  $status = UploadStatus::OPEN;
182  break;
183  case "inprogress":
184  $status = UploadStatus::IN_PROGRESS;
185  break;
186  case "closed":
187  $status = UploadStatus::CLOSED;
188  break;
189  case "rejected":
190  $status = UploadStatus::REJECTED;
191  break;
192  default:
193  $status = null;
194  }
195  }
196  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
197  $username = $query[self::FILTER_ASSIGNEE];
198  if (strcasecmp($username, "-me-") === 0) {
199  $assignee = $this->restHelper->getUserId();
200  } elseif (strcasecmp($username, "-unassigned-") === 0) {
201  $assignee = 1;
202  } else {
203  $assignee = $this->restHelper->getUserDao()->getUserByName($username);
204  if (empty($assignee)) {
205  throw new HttpNotFoundException("No user with user name '$username'");
206  }
207  $assignee = $assignee['user_pk'];
208  }
209  }
210  if (array_key_exists(self::FILTER_DATE, $query)) {
211  $date = filter_var($query[self::FILTER_DATE], FILTER_VALIDATE_REGEXP,
212  ["options" => [
213  "regexp" => "/^\d{4}\-\d{2}\-\d{2}$/",
214  "flags" => FILTER_NULL_ON_FAILURE
215  ]]);
216  $since = strtotime($date);
217  }
218  if ($apiVersion == ApiVersion::V2) {
219  $page = $query[self::PAGE_PARAM] ?? "";
220  $limit = $query[self::LIMIT_PARAM] ?? "";
221  } else {
222  $page = $request->getHeaderLine(self::PAGE_PARAM);
223  $limit = $request->getHeaderLine(self::LIMIT_PARAM);
224  }
225  if (! empty($page) || $page == "0") {
226  $page = filter_var($page, FILTER_VALIDATE_INT);
227  if ($page <= 0) {
228  throw new HttpBadRequestException(
229  "page should be positive integer > 0");
230  }
231  } else {
232  $page = 1;
233  }
234  if (! empty($limit)) {
235  $limit = filter_var($limit, FILTER_VALIDATE_INT);
236  if ($limit < 1) {
237  throw new HttpBadRequestException(
238  "limit should be positive integer > 1");
239  }
240  } else {
241  $limit = self::UPLOAD_FETCH_LIMIT;
242  }
243 
244  if (isset($args['id'])) {
245  $id = intval($args['id']);
246  $this->uploadAccessible($id);
247  $this->isAdj2nestDone($id);
248  }
249  $options = [
250  "folderId" => $folderId,
251  "name" => $name,
252  "status" => $status,
253  "assignee" => $assignee,
254  "since" => $since
255  ];
256  list($pages, $uploads) = $this->dbHelper->getUploads(
257  $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $limit,
258  $page, $id, $options, $recursive, $apiVersion);
259  if ($id !== null && ! empty($uploads)) {
260  $uploads = $uploads[0];
261  $pages = 1;
262  }
263  return $response->withHeader("X-Total-Pages", $pages)->withJson($uploads,
264  200);
265  }
266 
276  public function uploadDownload($request, $response, $args)
277  {
279  $ui_download = $this->restHelper->getPlugin('download');
280  $id = null;
281 
282  if (isset($args['id'])) {
283  $id = intval($args['id']);
284  $this->uploadAccessible($id);
285  }
286  $this->isAdj2nestDone($id);
287  $dbManager = $this->restHelper->getDbHelper()->getDbManager();
288  $uploadDao = $this->restHelper->getUploadDao();
289  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
290  $itemTreeBounds = $uploadDao->getParentItemBounds($id,$uploadTreeTableName);
291  $sql = "SELECT pfile_fk, ufile_name FROM $uploadTreeTableName " .
292  "WHERE uploadtree_pk=$1";
293  $params = array($itemTreeBounds->getItemId());
294  $descendants = $dbManager->getSingleRow($sql, $params,
295  __METHOD__ . "." . $uploadTreeTableName);
296  if (empty($descendants)) {
297  throw new HttpNotFoundException("Upload file not found.");
298  }
299  $path= RepPath(($descendants['pfile_fk']));
300  $responseFile = $ui_download->getDownload($path, $descendants['ufile_name']);
301  $responseContent = $responseFile->getFile();
302  $newResponse = $response->withHeader('Content-Description',
303  'File Transfer')
304  ->withHeader('Content-Type',
305  $responseContent->getMimeType())
306  ->withHeader('Content-Disposition',
307  $responseFile->headers->get('Content-Disposition'))
308  ->withHeader('Cache-Control', 'must-revalidate')
309  ->withHeader('Pragma', 'private')
310  ->withHeader('Content-Length', filesize($responseContent->getPathname()));
311  $sf = new StreamFactory();
312  return $newResponse->withBody(
313  $sf->createStreamFromFile($responseContent->getPathname())
314  );
315  }
316 
326  public function getUploadSummary($request, $response, $args)
327  {
328  $id = intval($args['id']);
329  $query = $request->getQueryParams();
330  $selectedAgentId = $query['agentId'] ?? null;
331  $agentDao = $this->container->get('dao.agent');
332  $this->uploadAccessible($id);
333  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
334  throw new HttpNotFoundException("Agent does not exist");
335  }
336  $this->isAdj2nestDone($id);
337  $uploadHelper = new UploadHelper();
338  $uploadSummary = $uploadHelper->generateUploadSummary($id, $this->restHelper->getGroupId());
339  $browseLicense = $this->restHelper->getPlugin('license');
340  $uploadDao = $this->restHelper->getUploadDao();
341  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
342  $itemTreeBounds = $uploadDao->getParentItemBounds($id, $uploadTreeTableName);
343  $scanJobProxy = new ScanJobProxy($agentDao, $id);
344  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
345  $scanJobProxy->createAgentStatus($scannerAgents);
346  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
347  $res = $browseLicense->createLicenseHistogram("", "", $itemTreeBounds, $selectedAgentIds, $this->restHelper->getGroupId());
348  $uploadSummary->setUniqueConcludedLicenses($res['editedUniqueLicenseCount']);
349  $uploadSummary->setTotalConcludedLicenses($res['editedLicenseCount']);
350  $uploadSummary->setTotalLicenses($res['scannerLicenseCount']);
351  $uploadSummary->setUniqueLicenses($res['uniqueLicenseCount']);
352  $uploadSummary->setConcludedNoLicenseFoundCount($res['editedNoLicenseFoundCount']);
353  $uploadSummary->setFileCount($res['fileCount']);
354  $uploadSummary->setNoScannerLicenseFoundCount($res['noScannerLicenseFoundCount']);
355  $uploadSummary->setScannerUniqueLicenseCount($res['scannerUniqueLicenseCount']);
356 
357  return $response->withJson($uploadSummary->getArray(), 200);
358  }
359 
369  public function deleteUpload($request, $response, $args)
370  {
371  require_once dirname(__DIR__, 4) . "/delagent/ui/delete-helper.php";
372  $id = intval($args['id']);
373 
374  $this->uploadAccessible($id);
375  $result = TryToDelete($id, $this->restHelper->getUserId(),
376  $this->restHelper->getGroupId(), $this->restHelper->getUploadDao());
377  if ($result->getDeleteMessageCode() !== DeleteMessages::SUCCESS) {
378  if (ApiVersion::getVersion($request) == ApiVersion::V2 &&
379  $result->getDeleteMessageCode() === DeleteMessages::NO_PERMISSION) {
380  throw new HttpForbiddenException($result->getDeleteMessageString());
381  }
383  $result->getDeleteMessageString());
384  }
385  $returnVal = new Info(202, "Delete Job for file with id " . $id,
386  InfoType::INFO);
387  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
388  }
389 
398  public function moveUpload($request, $response, $args)
399  {
400  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
401  $queryParams = $request->getQueryParams();
402  $action = $queryParams['action'] ?? "";
403  } else {
404  $action = $request->getHeaderLine('action');
405  }
406  if (strtolower($action) == "move") {
407  $copy = false;
408  } else {
409  $copy = true;
410  }
411  return $this->changeUpload($request, $response, $args, $copy);
412  }
413 
424  private function changeUpload($request, $response, $args, $isCopy)
425  {
426  $queryParams = $request->getQueryParams();
427  $isApiVersionV2 = (ApiVersion::getVersion($request) == ApiVersion::V2);
428  $paramType = ($isApiVersionV2) ? 'parameter' : 'header';
429 
430  if ((!$isApiVersionV2 && !$request->hasHeader('folderId') || $isApiVersionV2 && !isset($queryParams['folderId']))
431  || !is_numeric($newFolderID = ($isApiVersionV2 ? $queryParams['folderId'] : $request->getHeaderLine('folderId')))) {
432  throw new HttpBadRequestException("For API version " . ($isApiVersionV2 ? 'V2' : 'V1') . ", 'folderId' $paramType should be present and an integer.");
433  }
434 
435  $id = intval($args['id']);
436  $returnVal = $this->restHelper->copyUpload($id, $newFolderID, $isCopy);
437  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
438  }
439 
449  public function postUpload($request, $response, $args)
450  {
451  $reqBody = $this->getParsedBody($request);
452  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
453  $uploadType = $reqBody['uploadType'] ?? null;
454  $folderId = $reqBody['folderId'] ?? null;
455  $description = $reqBody['uploadDescription'] ?? "";
456  $public = $reqBody['public'] ?? null;
457  $applyGlobal = filter_var($reqBody['applyGlobal'] ?? null,
458  FILTER_VALIDATE_BOOLEAN);
459  $ignoreScm = $reqBody['ignoreScm'] ?? null;
460  $excludefolder = $reqBody['excludefolder'] ?? false;
461  } else {
462  $uploadType = $request->getHeaderLine('uploadType');
463  $folderId = $request->getHeaderLine('folderId');
464  $description = $request->getHeaderLine('uploadDescription');
465  $public = $request->getHeaderLine('public');
466  $applyGlobal = filter_var($request->getHeaderLine('applyGlobal'),
467  FILTER_VALIDATE_BOOLEAN);
468  $ignoreScm = $request->getHeaderLine('ignoreScm');
469  }
470 
471  $public = empty($public) ? 'protected' : $public;
472 
473  if (empty($uploadType)) {
474  throw new HttpBadRequestException("Require uploadType");
475  }
476  $scanOptions = [];
477  if (array_key_exists('scanOptions', $reqBody)) {
478  if ($uploadType == 'file') {
479  $scanOptions = json_decode($reqBody['scanOptions'], true);
480  if (json_last_error() !== JSON_ERROR_NONE || ! is_array($scanOptions)) {
481  throw new HttpBadRequestException("Invalid scanOptions JSON");
482  }
483  } else {
484  $scanOptions = $reqBody['scanOptions'];
485  }
486  }
487 
488  if (! is_array($scanOptions)) {
489  $scanOptions = [];
490  }
491 
492  $uploadHelper = new UploadHelper();
493 
494  if ($uploadType != "file" && (empty($reqBody) ||
495  ! array_key_exists("location", $reqBody))) {
496  throw new HttpBadRequestException(
497  "Require location object if uploadType != file");
498  }
499  if (empty($folderId) ||
500  !is_numeric($folderId) ||
501  intval($folderId) <= 0) {
502  throw new HttpBadRequestException("folderId must be a positive integer!");
503  }
504 
505  $allFolderIds = $this->restHelper->getFolderDao()->getAllFolderIds();
506  if (!in_array($folderId, $allFolderIds)) {
507  throw new HttpNotFoundException("folderId $folderId does not exists!");
508  }
509  if (!$this->restHelper->getFolderDao()->isFolderAccessible($folderId,
510  $this->restHelper->getUserId())) {
511  throw new HttpForbiddenException("folderId $folderId is not accessible!");
512  }
513 
514  $locationObject = [];
515  if (array_key_exists("location", $reqBody)) {
516  $locationObject = $reqBody["location"];
517  } elseif ($uploadType != 'file') {
518  throw new HttpBadRequestException(
519  "Require location object if uploadType != file");
520  }
521 
522  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
523  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
524  $folderId, $description, $public, $ignoreScm, $uploadType,
525  $applyGlobal, $excludefolder);
526  } else {
527  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
528  $folderId, $description, $public, $ignoreScm, $uploadType,
529  $applyGlobal);
530  }
531  $status = $uploadResponse[0];
532  $message = $uploadResponse[1];
533  $statusDescription = $uploadResponse[2];
534  if (! $status) {
535  throw new HttpInternalServerErrorException($message . "\n" .
536  $statusDescription);
537  }
538 
539  $uploadId = $uploadResponse[3];
540  if (! empty($scanOptions)) {
541  $info = $uploadHelper->handleScheduleAnalysis(intval($uploadId),
542  intval($folderId), $scanOptions, true, ApiVersion::getVersion($request));
543  if ($info->getCode() == 201) {
544  $info = new Info($info->getCode(), intval($uploadId), $info->getType());
545  }
546  } else {
547  $info = new Info(201, intval($uploadId), InfoType::INFO);
548  }
549  if (array_key_exists("mainLicense", $reqBody) &&
550  ! empty($reqBody["mainLicense"])) {
551  global $container;
553  $licenseDao = $container->get('dao.license');
554  $mainLicense = $licenseDao
555  ->getLicenseByShortName($reqBody["mainLicense"]);
556  if ($mainLicense !== null) {
558  $clearingDao = $container->get('dao.clearing');
559  $clearingDao->makeMainLicense($uploadId,
560  $this->restHelper->getGroupId(), $mainLicense->getId());
561  }
562  }
563  return $response->withJson($info->getArray(), $info->getCode());
564  }
565 
575  public function getUploadLicenses($request, $response, $args)
576  {
577  $id = intval($args['id']);
578  $query = $request->getQueryParams();
579  $apiVersion = ApiVersion::getVersion($request);
580  if ($apiVersion == ApiVersion::V2) {
581  $page = $query['page'] ?? "";
582  $limit = $query['limit'] ?? "";
583  } else {
584  $page = $request->getHeaderLine("page");
585  $limit = $request->getHeaderLine("limit");
586  }
587  if (! array_key_exists(self::AGENT_PARAM, $query)) {
588  throw new HttpBadRequestException("agent parameter missing from query.");
589  }
590  $agents = explode(",", $query[self::AGENT_PARAM]);
591  $containers = true;
592  if (array_key_exists(self::CONTAINER_PARAM, $query)) {
593  $containers = (strcasecmp($query[self::CONTAINER_PARAM], "true") === 0);
594  }
595 
596  $license = true;
597  if (array_key_exists('license', $query)) {
598  $license = (strcasecmp($query['license'], "true") === 0);
599  }
600 
601  $copyright = false;
602  if (array_key_exists('copyright', $query)) {
603  $copyright = (strcasecmp($query['copyright'], "true") === 0);
604  }
605 
606  if (!$license && !$copyright) {
607  throw new HttpBadRequestException(
608  "'license' and 'copyright' atleast one should be true.");
609  }
610 
611  $this->uploadAccessible($id);
612  $this->isAdj2nestDone($id);
613 
614  $this->areAgentsScheduled($id, $agents, $response);
615 
616  /*
617  * check if page && limit are numeric, if existing
618  */
619  if ((! ($page==='') && (! is_numeric($page) || $page < 1)) ||
620  (! ($limit==='') && (! is_numeric($limit) || $limit < 1))) {
621  throw new HttpBadRequestException(
622  "page and limit need to be positive integers!");
623  }
624 
625  // set page to 1 by default
626  if (empty($page)) {
627  $page = 1;
628  }
629 
630  // set limit to 50 by default and max as 1000
631  if (empty($limit)) {
632  $limit = 50;
633  } else if ($limit > 1000) {
634  $limit = 1000;
635  }
636 
637  $uploadHelper = new UploadHelper();
638  list($licenseList, $count) = $uploadHelper->getUploadLicenseList($id, $agents, $containers, $license, $copyright, $page-1, $limit, $apiVersion);
639  $totalPages = intval(ceil($count / $limit));
640  return $response->withHeader("X-Total-Pages", $totalPages)->withJson($licenseList, 200);
641  }
642 
652  public function getUploadCopyrights($request, $response, $args)
653  {
654  $id = intval($args['id']);
655  $this->uploadAccessible($id);
656  $this->isAdj2nestDone($id);
657  $uploadHelper = new UploadHelper();
658  $licenseList = $uploadHelper->getUploadCopyrightList($id);
659  return $response->withJson($licenseList, 200);
660  }
661 
671  public function updateUpload($request, $response, $args)
672  {
673  $id = intval($args['id']);
674  $query = $request->getQueryParams();
675  $userDao = $this->restHelper->getUserDao();
676  $userId = $this->restHelper->getUserId();
677  $groupId = $this->restHelper->getGroupId();
678  $isJsonRequest = $this->isJsonRequest($request);
679 
680  $perm = $userDao->isAdvisorOrAdmin($userId, $groupId);
681  if (!$perm) {
682  throw new HttpForbiddenException("Not advisor or admin of current group. " .
683  "Can not update upload.");
684  }
685  $uploadBrowseProxy = new UploadBrowseProxy(
686  $groupId,
687  $perm,
688  $this->dbHelper->getDbManager()
689  );
690 
691  $assignee = null;
692  $status = null;
693  $comment = null;
694  $newName = null;
695  $newDescription = null;
696 
697  if ($isJsonRequest) {
698  $bodyContent = $this->getParsedBody($request);
699  } else {
700  $body = $request->getBody();
701  $bodyContent = $body->getContents();
702  $body->close();
703  }
704 
705  // Handle assignee info
706  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
707  $assignee = filter_var($query[self::FILTER_ASSIGNEE], FILTER_VALIDATE_INT);
708  $userList = $userDao->getUserChoices($groupId);
709  if (!array_key_exists($assignee, $userList)) {
710  throw new HttpNotFoundException(
711  "New assignee does not have permission on upload.");
712  }
713  $uploadBrowseProxy->updateTable("assignee", $id, $assignee);
714  }
715  // Handle new status
716  if (
717  array_key_exists(self::FILTER_STATUS, $query) &&
718  in_array(strtolower($query[self::FILTER_STATUS]), self::VALID_STATUS)
719  ) {
720  $newStatus = strtolower($query[self::FILTER_STATUS]);
721  $comment = '';
722  if (in_array($newStatus, ["closed", "rejected"])) {
723  if ($isJsonRequest && array_key_exists("comment", $bodyContent)) {
724  $comment = $bodyContent["comment"];
725  } else {
726  $comment = $bodyContent;
727  }
728  }
729  $status = 0;
730  if ($newStatus == self::VALID_STATUS[1]) {
731  $status = UploadStatus::IN_PROGRESS;
732  } elseif ($newStatus == self::VALID_STATUS[2]) {
733  $status = UploadStatus::CLOSED;
734  } elseif ($newStatus == self::VALID_STATUS[3]) {
735  $status = UploadStatus::REJECTED;
736  } else {
737  $status = UploadStatus::OPEN;
738  }
739  $uploadBrowseProxy->setStatusAndComment($id, $status, $comment);
740  }
741  // Handle update of name
742  if (
743  $isJsonRequest &&
744  array_key_exists(self::FILTER_NAME, $bodyContent) &&
745  strlen(trim($bodyContent[self::FILTER_NAME])) > 0
746  ) {
747  $newName = trim($bodyContent[self::FILTER_NAME]);
748  }
749  // Handle update of description
750  if (
751  $isJsonRequest &&
752  array_key_exists("uploadDescription", $bodyContent) &&
753  strlen(trim($bodyContent["uploadDescription"])) > 0
754  ) {
755  $newDescription = trim($bodyContent["uploadDescription"]);
756  }
757  if ($newName != null || $newDescription != null) {
759  $uploadProperties = $this->restHelper->getPlugin('upload_properties');
760  $updated = $uploadProperties->UpdateUploadProperties($id, $newName, $newDescription);
761  if ($updated == 2) {
762  throw new HttpBadRequestException("Invalid request to update upload name and description.");
763  }
764  }
765 
766  $returnVal = new Info(202, "Upload updated successfully.", InfoType::INFO);
767  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
768  }
769 
775  private function isAdj2nestDone($id): void
776  {
777  $itemTreeBounds = $this->restHelper->getUploadDao()->getParentItemBounds(
778  $id);
779  if ($itemTreeBounds === false || empty($itemTreeBounds->getLeft())) {
781  "Ununpack job not started. Please check job status at " .
782  "/api/v1/jobs?upload=" . $id))
783  ->setHeaders(['Retry-After' => '60',
784  'Look-at' => "/api/v1/jobs?upload=" . $id]);
785  }
786  }
787 
797  private function areAgentsScheduled($uploadId, $agents, $response): void
798  {
799  global $container;
800  $agentDao = $container->get('dao.agent');
801 
802  $agentList = array_keys(AgentRef::AGENT_LIST);
803  $intersectArray = array_intersect($agents, $agentList);
804 
805  if (count($agents) != count($intersectArray)) {
806  throw new HttpBadRequestException("Agent should be any of " .
807  implode(", ", $agentList) . ". " . implode(",", $agents) . " passed.");
808  } else {
809  // Agent is valid, check if they have ars tables.
810  foreach ($agents as $agent) {
811  if (! $agentDao->arsTableExists($agent)) {
813  "Agent $agent not scheduled for the upload. " .
814  "Please POST to /jobs");
815  }
816  }
817  }
818 
819  $scanProxy = new ScanJobProxy($agentDao, $uploadId);
820  $agentList = $scanProxy->createAgentStatus($agents);
821 
822  foreach ($agentList as $agent) {
823  if (! array_key_exists('currentAgentId', $agent)) {
825  "Agent " . $agent["agentName"] .
826  " not scheduled for the upload. Please POST to /jobs");
827  }
828  if (array_key_exists('isAgentRunning', $agent) &&
829  $agent['isAgentRunning']) {
831  "Agent " . $agent["agentName"] . " is running. " .
832  "Please check job status at /api/v1/jobs?upload=" . $uploadId))
833  ->setHeaders(['Retry-After' => '60',
834  'Look-at' => "/api/v1/jobs?upload=" . $uploadId]);
835  }
836  }
837  }
838 
848  public function setUploadPermissions($request, $response, $args)
849  {
850  $returnVal = null;
851  // checking if the scheduler is running or not
852  $commu_status = fo_communicate_with_scheduler('status', $response_from_scheduler, $error_info);
853  if (!$commu_status) {
854  throw new HttpServiceUnavailableException("Scheduler is not running!");
855  }
856  // Initialising upload-permissions plugin
857  global $container;
858  $restHelper = $container->get('helper.restHelper');
859  $uploadPermissionObj = $restHelper->getPlugin('upload_permissions');
860 
861  $dbManager = $this->dbHelper->getDbManager();
862  // parsing the request body
863  $reqBody = $this->getParsedBody($request);
864 
865  $folder_pk = intval($reqBody['folderId']);
866  $upload_pk = intval($args['id']);
867  $this->uploadAccessible($upload_pk);
868  $allUploadsPerm = $reqBody['allUploadsPermission'] ? 1 : 0;
869  $newgroup = intval($reqBody['groupId']);
870  $newperm = $this->getEquivalentValueForPermission($reqBody['newPermission']);
871  $public_perm = isset($reqBody['publicPermission']) ? $this->getEquivalentValueForPermission($reqBody['publicPermission']) : -1;
872 
873  $query = "SELECT perm, perm_upload_pk FROM perm_upload WHERE upload_fk=$1 and group_fk=$2;";
874  $result = $dbManager->getSingleRow($query, [$upload_pk, $newgroup], __METHOD__.".getOldPerm");
875  $perm_upload_pk = 0;
876  $perm = 0;
877  if (!empty($result)) {
878  $perm_upload_pk = intVal($result['perm_upload_pk']);
879  $perm = $newperm;
880  }
881 
882  $uploadPermissionObj->editPermissionsForUpload($commu_status, $folder_pk, $upload_pk, $allUploadsPerm, $perm_upload_pk, $perm, $newgroup, $newperm, $public_perm);
883 
884  $returnVal = new Info(202, "Permissions updated successfully!", InfoType::INFO);
885  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
886  }
887 
888  public function getEquivalentValueForPermission($perm)
889  {
890  switch ($perm) {
891  case 'read_only':
892  return Auth::PERM_READ;
893  case 'read_write':
894  return Auth::PERM_WRITE;
895  case 'clearing_admin':
896  return Auth::PERM_CADMIN;
897  case 'admin':
898  return Auth::PERM_ADMIN;
899  default:
900  return Auth::PERM_NONE;
901  }
902  }
903 
913  public function getGroupsWithPermissions($request, $response, $args)
914  {
915  $apiVersion = ApiVersion::getVersion($request);
916  $upload_pk = intval($args['id']);
917  $this->uploadAccessible($upload_pk);
918  $publicPerm = $this->restHelper->getUploadPermissionDao()->getPublicPermission($upload_pk);
919  $permGroups = $this->restHelper->getUploadPermissionDao()->getPermissionGroups($upload_pk);
920 
921  // Removing the perm_upload_pk parameter in response
922  $finalPermGroups = [];
923  foreach ($permGroups as $value) {
924  $groupPerm = new GroupPermission($value['perm'], $value['group_pk'], $value['group_name']);
925  $finalPermGroups[] = $groupPerm->getArray($apiVersion);
926  }
927  $res = new Permissions($publicPerm, $finalPermGroups);
928  return $response->withJson($res->getArray($apiVersion), 200);
929  }
930 
940  public function getMainLicenses($request, $response, $args)
941  {
942  $uploadId = intval($args['id']);
943  $this->uploadAccessible($uploadId);
944 
946  $clearingDao = $this->container->get('dao.clearing');
947  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
948  $licenseDao = $this->container->get('dao.license');
949  $licenses = array();
950 
951  foreach ($licenseIds as $value) {
952  $licenseId = intval($value);
953  $obligations = $licenseDao->getLicenseObligations([$licenseId],
954  false);
955  $obligations = array_merge($obligations,
956  $licenseDao->getLicenseObligations([$licenseId], true));
957  $obligationList = [];
958  foreach ($obligations as $obligation) {
959  $obligationList[] = new Obligation(
960  $obligation['ob_pk'],
961  $obligation['ob_topic'],
962  $obligation['ob_type'],
963  $obligation['ob_text'],
964  $obligation['ob_classification'],
965  $obligation['ob_comment']
966  );
967  }
968  $license = $licenseDao->getLicenseById($licenseId);
969  $licenseObj = new License(
970  $license->getId(),
971  $license->getShortName(),
972  $license->getFullName(),
973  $license->getText(),
974  $license->getUrl(),
975  $obligationList,
976  $license->getRisk()
977  );
978  $licenses[] = $licenseObj->getArray();
979  }
980  return $response->withJson($licenses, 200);
981  }
982 
992  public function setMainLicense($request, $response, $args)
993  {
994  $uploadId = intval($args['id']);
995  $body = $this->getParsedBody($request);
996  $shortName = $body['shortName'];
997  $licenseDao = $this->container->get('dao.license');
998  $clearingDao = $this->container->get('dao.clearing');
999 
1000  $this->uploadAccessible($uploadId);
1001 
1002  if (empty($shortName)) {
1003  throw new HttpBadRequestException("Short name missing from request.");
1004  }
1005  $license = $licenseDao->getLicenseByShortName($shortName,
1006  $this->restHelper->getGroupId());
1007 
1008  if ($license === null) {
1009  throw new HttpNotFoundException(
1010  "No license with shortname '$shortName' found.");
1011  }
1012 
1013  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1014  if (in_array($license->getId(), $licenseIds)) {
1015  throw new HttpBadRequestException(
1016  "License already exists for this upload.");
1017  }
1018 
1020  $clearingDao = $this->container->get('dao.clearing');
1021  $clearingDao->makeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1022  $returnVal = new Info(200, "Successfully added new main license", InfoType::INFO);
1023  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1024  }
1025 
1026  /***
1027  * Remove the main license from the upload
1028  *
1029  * @param ServerRequestInterface $request
1030  * @param ResponseHelper $response
1031  * @param array $args
1032  * @return ResponseHelper
1033  * @throws HttpErrorException
1034  */
1035  public function removeMainLicense($request, $response, $args)
1036  {
1037  $uploadId = intval($args['id']);
1038  $shortName = $args['shortName'];
1039  $licenseDao = $this->container->get('dao.license');
1040  $clearingDao = $this->container->get('dao.clearing');
1041  $license = $licenseDao->getLicenseByShortName($shortName, $this->restHelper->getGroupId());
1042 
1043  $this->uploadAccessible($uploadId);
1044 
1045  if ($license === null) {
1046  throw new HttpNotFoundException(
1047  "No license with shortname '$shortName' found.");
1048  }
1049  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1050  if (!in_array($license->getId(), $licenseIds)) {
1051  throw new HttpBadRequestException(
1052  "License '$shortName' is not a main license for this upload.");
1053  }
1054 
1055  $clearingDao = $this->container->get('dao.clearing');
1056  $clearingDao->removeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1057  $returnVal = new Info(200, "Main license removed successfully.", InfoType::INFO);
1058 
1059  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1060  }
1061 
1071  public function getClearingProgressInfo($request, $response, $args)
1072  {
1073  $uploadId = intval($args['id']);
1074  $uploadDao = $this->restHelper->getUploadDao();
1075 
1076  $this->uploadAccessible($uploadId);
1077 
1078  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1079 
1080  $noLicenseUploadTreeView = new UploadTreeProxy($uploadId,
1081  array(UploadTreeProxy::OPT_SKIP_THESE => "noLicense",
1082  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1083  $uploadTreeTableName,
1084  'no_license_uploadtree' . $uploadId);
1085 
1086  $filesOfInterest = $noLicenseUploadTreeView->count();
1087 
1088  $nonClearedUploadTreeView = new UploadTreeProxy($uploadId,
1089  array(UploadTreeProxy::OPT_SKIP_THESE => "alreadyCleared",
1090  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1091  $uploadTreeTableName,
1092  'already_cleared_uploadtree' . $uploadId);
1093  $filesToBeCleared = $nonClearedUploadTreeView->count();
1094 
1095  $filesAlreadyCleared = $filesOfInterest - $filesToBeCleared;
1096 
1097  $res = [
1098  "totalFilesOfInterest" => intval($filesOfInterest),
1099  "totalFilesCleared" => intval($filesAlreadyCleared),
1100  ];
1101  return $response->withJson($res, 200);
1102  }
1103 
1113  public function getLicensesHistogram($request, $response, $args)
1114  {
1115  $agentDao = $this->container->get('dao.agent');
1116  $clearingDao = $this->container->get('dao.clearing');
1117  $licenseDao = $this->container->get('dao.license');
1118 
1119  $uploadId = intval($args['id']);
1120  $uploadDao = $this->restHelper->getUploadDao();
1121  $query = $request->getQueryParams();
1122  $selectedAgentId = $query['agentId'] ?? null;
1123 
1124  $this->uploadAccessible($uploadId);
1125 
1126  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1127  throw new HttpNotFoundException("Agent does not exist.");
1128  }
1129 
1130  $scannerAgents = array_keys($this->agentNames);
1131  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1132  $scanJobProxy->createAgentStatus($scannerAgents);
1133  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1134  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1135  $editedLicenses = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1136  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1137  $scannedLicenses = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1138  $allScannerLicenseNames = array_keys($scannedLicenses);
1139  $allEditedLicenseNames = array_keys($editedLicenses);
1140  $allLicNames = array_unique(array_merge($allScannerLicenseNames, $allEditedLicenseNames));
1141  $realLicNames = array_diff($allLicNames, array(LicenseDao::NO_LICENSE_FOUND));
1142  $totalScannerLicenseCount = 0;
1143  $editedTotalLicenseCount = 0;
1144 
1145  $res = array();
1146  foreach ($realLicNames as $licenseShortName) {
1147  $count = 0;
1148  if (array_key_exists($licenseShortName, $scannedLicenses)) {
1149  $count = $scannedLicenses[$licenseShortName]['unique'];
1150  $rfId = $scannedLicenses[$licenseShortName]['rf_pk'];
1151  } else {
1152  $rfId = $editedLicenses[$licenseShortName]['rf_pk'];
1153  }
1154  $editedCount = array_key_exists($licenseShortName, $editedLicenses) ? $editedLicenses[$licenseShortName]['count'] : 0;
1155  $totalScannerLicenseCount += $count;
1156  $editedTotalLicenseCount += $editedCount;
1157  $scannerCountLink = $count;
1158  $editedLink = $editedCount;
1159 
1160  $res[] = array($scannerCountLink, $editedLink, array($licenseShortName, $rfId));
1161  }
1162 
1163  $outputArray = [];
1164 
1165  foreach ($res as $item) {
1166  $outputArray[] = [
1167  "id" => intval($item[2][1]),
1168  "name" => $item[2][0],
1169  "scannerCount" => intval($item[0]),
1170  "concludedCount" => intval($item[1]),
1171  ];
1172  }
1173  return $response->withJson($outputArray, 200);
1174  }
1175 
1185  public function getAllAgents($request, $response, $args)
1186  {
1187  $uploadId = intval($args['id']);
1188 
1189  $this->uploadAccessible($uploadId);
1190 
1191  $scannerAgents = array_keys($this->agentNames);
1192  $agentDao = $this->container->get('dao.agent');
1193  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1194  $res = $scanJobProxy->createAgentStatus($scannerAgents);
1195 
1196  $outputArray = [];
1197  foreach ($res as &$item) {
1198  $successfulAgents = [];
1199  if (count($item['successfulAgents']) > 0) {
1200  $item['isAgentRunning'] = false;
1201  } else {
1202  $item['currentAgentId'] = $agentDao->getCurrentAgentRef($item["agentName"])->getAgentId();
1203  $item['currentAgentRev'] = "";
1204  }
1205  foreach ($item['successfulAgents'] as &$agent) {
1206  $successfulAgent = new SuccessfulAgent(intval($agent['agent_id']), $agent['agent_rev'], $agent['agent_name']);
1207  $successfulAgents[] = $successfulAgent->getArray(ApiVersion::getVersion($request));
1208  }
1209  $agent = new Agent($successfulAgents, $item['uploadId'], $item['agentName'], $item['currentAgentId'], $item['currentAgentRev'], $item['isAgentRunning']);
1210  $outputArray[] = $agent->getArray(ApiVersion::getVersion($request));
1211  }
1212  return $response->withJson($outputArray, 200);
1213  }
1214 
1224  public function getEditedLicenses($request, $response, $args)
1225  {
1226  $uploadId = intval($args['id']);
1227 
1228  $this->uploadAccessible($uploadId);
1229 
1230  $clearingDao = $this->container->get('dao.clearing');
1231  $uploadDao = $this->restHelper->getUploadDao();
1232  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1233  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1234  $res = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1235  $outputArray = [];
1236 
1237  foreach ($res as $key => $value) {
1238  $editedLicense = new EditedLicense(intval($value["rf_pk"]), $key, intval($value["count"]), $value["spdx_id"]);
1239  $outputArray[] = $editedLicense->getArray(ApiVersion::getVersion($request));
1240  }
1241  return $response->withJson($outputArray, 200);
1242  }
1243 
1253  public function getReuseReportSummary($request, $response, $args)
1254  {
1255  $uploadId = intval($args['id']);
1256  $this->uploadAccessible($uploadId);
1257 
1259  $reuseReportProcess = $this->container->get('businessrules.reusereportprocessor');
1260  $res = $reuseReportProcess->getReuseSummary($uploadId);
1261  return $response->withJson($res, 200);
1262  }
1263 
1273  public function getScannedLicenses($request, $response, $args)
1274  {
1275  $uploadId = intval($args['id']);
1276  $query = $request->getQueryParams();
1277  $selectedAgentId = $query['agentId'] ?? null;
1278  $licenseDao = $this->container->get('dao.license');
1279 
1280  $this->uploadAccessible($uploadId);
1281  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1282  throw new HttpNotFoundException("Agent does not exist.");
1283  }
1284  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
1285  $scanJobProxy = new ScanJobProxy($this->agentDao, $uploadId);
1286  $scanJobProxy->createAgentStatus($scannerAgents);
1287  $uploadDao = $this->restHelper->getUploadDao();
1288  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1289  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1290  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1291  $res = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1292  $outputArray = [];
1293 
1294  foreach ($res as $key => $value) {
1295  $scannedLicense = new ScannedLicense(
1296  $value['rf_pk'],
1297  $key,
1298  $value['count'],
1299  $value['unique'],
1300  $value['spdx_id']
1301  );
1302  $outputArray[] = $scannedLicense->getArray(ApiVersion::getVersion($request));
1303  }
1304  return $response->withJson($outputArray, 200);
1305  }
1315  public function getAgentsRevision($request, $response, $args)
1316  {
1317  $agentDao = $this->container->get('dao.agent');
1318  $uploadId = intval($args['id']);
1319 
1320  $this->uploadAccessible($uploadId);
1321 
1322  $scannerAgents = array_keys($this->agentNames);
1323  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1324  $scanJobProxy->createAgentStatus($scannerAgents);
1325 
1326  $res = array();
1327  foreach ($scanJobProxy->getSuccessfulAgents() as $agent) {
1328  $res[] = array(
1329  "id" => $agent->getAgentId(),
1330  "name" => $agent->getAgentName(),
1331  "revision" => $agent->getAgentRevision(),
1332  );
1333  }
1334  return $response->withJson($res, 200);
1335  }
1336 
1346  public function getTopItem($request, $response, $args)
1347  {
1348  $uploadId = intval($args['id']);
1349  if (!$this->dbHelper->doesIdExist("upload", "upload_pk", $uploadId)) {
1350  $returnVal = new Info(404, "Upload does not exist", InfoType::ERROR);
1351  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1352  }
1353  $uploadDao = $this->restHelper->getUploadDao();
1354  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId,
1355  $uploadDao->getUploadtreeTableName($uploadId));
1356  if ($itemTreeBounds === false) {
1357  $error = new Info(500, "Unable to get top item.", InfoType::ERROR);
1358  return $response->withJson($error->getArray(), $error->getCode());
1359  }
1360  $info = new Info(200, $itemTreeBounds->getItemId(), InfoType::INFO);
1361  return $response->withJson($info->getArray(), $info->getCode());
1362  }
1363 }
Messages which can be generated by delagent.
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
Fossology exception.
Definition: Exception.php:15
Base controller for REST calls.
getParsedBody(ServerRequestInterface $request)
Parse request body as JSON and return associative PHP array.
areAgentsScheduled($uploadId, $agents, $response)
getClearingProgressInfo($request, $response, $args)
setUploadPermissions($request, $response, $args)
getGroupsWithPermissions($request, $response, $args)
changeUpload($request, $response, $args, $isCopy)
Override Slim response for withJson function.
Handle new file uploads from Slim framework and move to FOSSology.
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
RepPath($PfilePk, $Repo="files")
Given a pfile id, retrieve the pfile path.
Definition: common-repo.php:58
fo_communicate_with_scheduler($input, &$output, &$error_msg)
Communicate with scheduler, send commands to the scheduler, then get the output.
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690
Definition: monk.h:55