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  $dbManager = $this->restHelper->getDbHelper()->getDbManager();
287  $uploadDao = $this->restHelper->getUploadDao();
288  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
289  $itemTreeBounds = $uploadDao->getParentItemBounds($id,$uploadTreeTableName);
290  $sql = "SELECT pfile_fk , ufile_name FROM uploadtree_a WHERE uploadtree_pk=$1";
291  $params = array($itemTreeBounds->getItemId());
292  $descendants = $dbManager->getSingleRow($sql,$params);
293  $path= RepPath(($descendants['pfile_fk']));
294  $responseFile = $ui_download->getDownload($path, $descendants['ufile_name']);
295  $responseContent = $responseFile->getFile();
296  $newResponse = $response->withHeader('Content-Description',
297  'File Transfer')
298  ->withHeader('Content-Type',
299  $responseContent->getMimeType())
300  ->withHeader('Content-Disposition',
301  $responseFile->headers->get('Content-Disposition'))
302  ->withHeader('Cache-Control', 'must-revalidate')
303  ->withHeader('Pragma', 'private')
304  ->withHeader('Content-Length', filesize($responseContent->getPathname()));
305  $sf = new StreamFactory();
306  return $newResponse->withBody(
307  $sf->createStreamFromFile($responseContent->getPathname())
308  );
309  }
310 
320  public function getUploadSummary($request, $response, $args)
321  {
322  $id = intval($args['id']);
323  $query = $request->getQueryParams();
324  $selectedAgentId = $query['agentId'] ?? null;
325  $agentDao = $this->container->get('dao.agent');
326  $this->uploadAccessible($id);
327  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
328  throw new HttpNotFoundException("Agent does not exist");
329  }
330  $this->isAdj2nestDone($id);
331  $uploadHelper = new UploadHelper();
332  $uploadSummary = $uploadHelper->generateUploadSummary($id, $this->restHelper->getGroupId());
333  $browseLicense = $this->restHelper->getPlugin('license');
334  $uploadDao = $this->restHelper->getUploadDao();
335  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
336  $itemTreeBounds = $uploadDao->getParentItemBounds($id, $uploadTreeTableName);
337  $scanJobProxy = new ScanJobProxy($agentDao, $id);
338  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
339  $scanJobProxy->createAgentStatus($scannerAgents);
340  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
341  $res = $browseLicense->createLicenseHistogram("", "", $itemTreeBounds, $selectedAgentIds, $this->restHelper->getGroupId());
342  $uploadSummary->setUniqueConcludedLicenses($res['editedUniqueLicenseCount']);
343  $uploadSummary->setTotalConcludedLicenses($res['editedLicenseCount']);
344  $uploadSummary->setTotalLicenses($res['scannerLicenseCount']);
345  $uploadSummary->setUniqueLicenses($res['uniqueLicenseCount']);
346  $uploadSummary->setConcludedNoLicenseFoundCount($res['editedNoLicenseFoundCount']);
347  $uploadSummary->setFileCount($res['fileCount']);
348  $uploadSummary->setNoScannerLicenseFoundCount($res['noScannerLicenseFoundCount']);
349  $uploadSummary->setScannerUniqueLicenseCount($res['scannerUniqueLicenseCount']);
350 
351  return $response->withJson($uploadSummary->getArray(), 200);
352  }
353 
363  public function deleteUpload($request, $response, $args)
364  {
365  require_once dirname(__DIR__, 4) . "/delagent/ui/delete-helper.php";
366  $id = intval($args['id']);
367 
368  $this->uploadAccessible($id);
369  $result = TryToDelete($id, $this->restHelper->getUserId(),
370  $this->restHelper->getGroupId(), $this->restHelper->getUploadDao());
371  if ($result->getDeleteMessageCode() !== DeleteMessages::SUCCESS) {
373  $result->getDeleteMessageString());
374  }
375  $returnVal = new Info(202, "Delete Job for file with id " . $id,
376  InfoType::INFO);
377  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
378  }
379 
388  public function moveUpload($request, $response, $args)
389  {
390  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
391  $queryParams = $request->getQueryParams();
392  $action = $queryParams['action'] ?? "";
393  } else {
394  $action = $request->getHeaderLine('action');
395  }
396  if (strtolower($action) == "move") {
397  $copy = false;
398  } else {
399  $copy = true;
400  }
401  return $this->changeUpload($request, $response, $args, $copy);
402  }
403 
414  private function changeUpload($request, $response, $args, $isCopy)
415  {
416  $queryParams = $request->getQueryParams();
417  $isApiVersionV2 = (ApiVersion::getVersion($request) == ApiVersion::V2);
418  $paramType = ($isApiVersionV2) ? 'parameter' : 'header';
419 
420  if ((!$isApiVersionV2 && !$request->hasHeader('folderId') || $isApiVersionV2 && !isset($queryParams['folderId']))
421  || !is_numeric($newFolderID = ($isApiVersionV2 ? $queryParams['folderId'] : $request->getHeaderLine('folderId')))) {
422  throw new HttpBadRequestException("For API version " . ($isApiVersionV2 ? 'V2' : 'V1') . ", 'folderId' $paramType should be present and an integer.");
423  }
424 
425  $id = intval($args['id']);
426  $returnVal = $this->restHelper->copyUpload($id, $newFolderID, $isCopy);
427  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
428  }
429 
439  public function postUpload($request, $response, $args)
440  {
441  $reqBody = $this->getParsedBody($request);
442  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
443  $uploadType = $reqBody['uploadType'] ?? null;
444  $folderId = $reqBody['folderId'] ?? null;
445  $description = $reqBody['uploadDescription'] ?? "";
446  $public = $reqBody['public'] ?? null;
447  $applyGlobal = filter_var($reqBody['applyGlobal'] ?? null,
448  FILTER_VALIDATE_BOOLEAN);
449  $ignoreScm = $reqBody['ignoreScm'] ?? null;
450  $excludefolder = $reqBody['excludefolder'] ?? false;
451  } else {
452  $uploadType = $request->getHeaderLine('uploadType');
453  $folderId = $request->getHeaderLine('folderId');
454  $description = $request->getHeaderLine('uploadDescription');
455  $public = $request->getHeaderLine('public');
456  $applyGlobal = filter_var($request->getHeaderLine('applyGlobal'),
457  FILTER_VALIDATE_BOOLEAN);
458  $ignoreScm = $request->getHeaderLine('ignoreScm');
459  }
460 
461  $public = empty($public) ? 'protected' : $public;
462 
463  if (empty($uploadType)) {
464  throw new HttpBadRequestException("Require uploadType");
465  }
466  $scanOptions = [];
467  if (array_key_exists('scanOptions', $reqBody)) {
468  if ($uploadType == 'file') {
469  $scanOptions = json_decode($reqBody['scanOptions'], true);
470  if (json_last_error() !== JSON_ERROR_NONE || ! is_array($scanOptions)) {
471  throw new HttpBadRequestException("Invalid scanOptions JSON");
472  }
473  } else {
474  $scanOptions = $reqBody['scanOptions'];
475  }
476  }
477 
478  if (! is_array($scanOptions)) {
479  $scanOptions = [];
480  }
481 
482  $uploadHelper = new UploadHelper();
483 
484  if ($uploadType != "file" && (empty($reqBody) ||
485  ! array_key_exists("location", $reqBody))) {
486  throw new HttpBadRequestException(
487  "Require location object if uploadType != file");
488  }
489  if (empty($folderId) ||
490  !is_numeric($folderId) ||
491  intval($folderId) <= 0) {
492  throw new HttpBadRequestException("folderId must be a positive integer!");
493  }
494 
495  $allFolderIds = $this->restHelper->getFolderDao()->getAllFolderIds();
496  if (!in_array($folderId, $allFolderIds)) {
497  throw new HttpNotFoundException("folderId $folderId does not exists!");
498  }
499  if (!$this->restHelper->getFolderDao()->isFolderAccessible($folderId,
500  $this->restHelper->getUserId())) {
501  throw new HttpForbiddenException("folderId $folderId is not accessible!");
502  }
503 
504  $locationObject = [];
505  if (array_key_exists("location", $reqBody)) {
506  $locationObject = $reqBody["location"];
507  } elseif ($uploadType != 'file') {
508  throw new HttpBadRequestException(
509  "Require location object if uploadType != file");
510  }
511 
512  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
513  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
514  $folderId, $description, $public, $ignoreScm, $uploadType,
515  $applyGlobal, $excludefolder);
516  } else {
517  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
518  $folderId, $description, $public, $ignoreScm, $uploadType,
519  $applyGlobal);
520  }
521  $status = $uploadResponse[0];
522  $message = $uploadResponse[1];
523  $statusDescription = $uploadResponse[2];
524  if (! $status) {
525  throw new HttpInternalServerErrorException($message . "\n" .
526  $statusDescription);
527  }
528 
529  $uploadId = $uploadResponse[3];
530  if (! empty($scanOptions)) {
531  $info = $uploadHelper->handleScheduleAnalysis(intval($uploadId),
532  intval($folderId), $scanOptions, true, ApiVersion::getVersion($request));
533  if ($info->getCode() == 201) {
534  $info = new Info($info->getCode(), intval($uploadId), $info->getType());
535  }
536  } else {
537  $info = new Info(201, intval($uploadId), InfoType::INFO);
538  }
539  if (array_key_exists("mainLicense", $reqBody) &&
540  ! empty($reqBody["mainLicense"])) {
541  global $container;
543  $licenseDao = $container->get('dao.license');
544  $mainLicense = $licenseDao
545  ->getLicenseByShortName($reqBody["mainLicense"]);
546  if ($mainLicense !== null) {
548  $clearingDao = $container->get('dao.clearing');
549  $clearingDao->makeMainLicense($uploadId,
550  $this->restHelper->getGroupId(), $mainLicense->getId());
551  }
552  }
553  return $response->withJson($info->getArray(), $info->getCode());
554  }
555 
565  public function getUploadLicenses($request, $response, $args)
566  {
567  $id = intval($args['id']);
568  $query = $request->getQueryParams();
569  $apiVersion = ApiVersion::getVersion($request);
570  if ($apiVersion == ApiVersion::V2) {
571  $page = $query['page'] ?? "";
572  $limit = $query['limit'] ?? "";
573  } else {
574  $page = $request->getHeaderLine("page");
575  $limit = $request->getHeaderLine("limit");
576  }
577  if (! array_key_exists(self::AGENT_PARAM, $query)) {
578  throw new HttpBadRequestException("agent parameter missing from query.");
579  }
580  $agents = explode(",", $query[self::AGENT_PARAM]);
581  $containers = true;
582  if (array_key_exists(self::CONTAINER_PARAM, $query)) {
583  $containers = (strcasecmp($query[self::CONTAINER_PARAM], "true") === 0);
584  }
585 
586  $license = true;
587  if (array_key_exists('license', $query)) {
588  $license = (strcasecmp($query['license'], "true") === 0);
589  }
590 
591  $copyright = false;
592  if (array_key_exists('copyright', $query)) {
593  $copyright = (strcasecmp($query['copyright'], "true") === 0);
594  }
595 
596  if (!$license && !$copyright) {
597  throw new HttpBadRequestException(
598  "'license' and 'copyright' atleast one should be true.");
599  }
600 
601  $this->uploadAccessible($id);
602  $this->isAdj2nestDone($id);
603 
604  $this->areAgentsScheduled($id, $agents, $response);
605 
606  /*
607  * check if page && limit are numeric, if existing
608  */
609  if ((! ($page==='') && (! is_numeric($page) || $page < 1)) ||
610  (! ($limit==='') && (! is_numeric($limit) || $limit < 1))) {
611  throw new HttpBadRequestException(
612  "page and limit need to be positive integers!");
613  }
614 
615  // set page to 1 by default
616  if (empty($page)) {
617  $page = 1;
618  }
619 
620  // set limit to 50 by default and max as 1000
621  if (empty($limit)) {
622  $limit = 50;
623  } else if ($limit > 1000) {
624  $limit = 1000;
625  }
626 
627  $uploadHelper = new UploadHelper();
628  list($licenseList, $count) = $uploadHelper->getUploadLicenseList($id, $agents, $containers, $license, $copyright, $page-1, $limit, $apiVersion);
629  $totalPages = intval(ceil($count / $limit));
630  return $response->withHeader("X-Total-Pages", $totalPages)->withJson($licenseList, 200);
631  }
632 
642  public function getUploadCopyrights($request, $response, $args)
643  {
644  $id = intval($args['id']);
645  $this->uploadAccessible($id);
646  $this->isAdj2nestDone($id);
647  $uploadHelper = new UploadHelper();
648  $licenseList = $uploadHelper->getUploadCopyrightList($id);
649  return $response->withJson($licenseList, 200);
650  }
651 
661  public function updateUpload($request, $response, $args)
662  {
663  $id = intval($args['id']);
664  $query = $request->getQueryParams();
665  $userDao = $this->restHelper->getUserDao();
666  $userId = $this->restHelper->getUserId();
667  $groupId = $this->restHelper->getGroupId();
668  $isJsonRequest = $this->isJsonRequest($request);
669 
670  $perm = $userDao->isAdvisorOrAdmin($userId, $groupId);
671  if (!$perm) {
672  throw new HttpForbiddenException("Not advisor or admin of current group. " .
673  "Can not update upload.");
674  }
675  $uploadBrowseProxy = new UploadBrowseProxy(
676  $groupId,
677  $perm,
678  $this->dbHelper->getDbManager()
679  );
680 
681  $assignee = null;
682  $status = null;
683  $comment = null;
684  $newName = null;
685  $newDescription = null;
686 
687  if ($isJsonRequest) {
688  $bodyContent = $this->getParsedBody($request);
689  } else {
690  $body = $request->getBody();
691  $bodyContent = $body->getContents();
692  $body->close();
693  }
694 
695  // Handle assignee info
696  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
697  $assignee = filter_var($query[self::FILTER_ASSIGNEE], FILTER_VALIDATE_INT);
698  $userList = $userDao->getUserChoices($groupId);
699  if (!array_key_exists($assignee, $userList)) {
700  throw new HttpNotFoundException(
701  "New assignee does not have permission on upload.");
702  }
703  $uploadBrowseProxy->updateTable("assignee", $id, $assignee);
704  }
705  // Handle new status
706  if (
707  array_key_exists(self::FILTER_STATUS, $query) &&
708  in_array(strtolower($query[self::FILTER_STATUS]), self::VALID_STATUS)
709  ) {
710  $newStatus = strtolower($query[self::FILTER_STATUS]);
711  $comment = '';
712  if (in_array($newStatus, ["closed", "rejected"])) {
713  if ($isJsonRequest && array_key_exists("comment", $bodyContent)) {
714  $comment = $bodyContent["comment"];
715  } else {
716  $comment = $bodyContent;
717  }
718  }
719  $status = 0;
720  if ($newStatus == self::VALID_STATUS[1]) {
721  $status = UploadStatus::IN_PROGRESS;
722  } elseif ($newStatus == self::VALID_STATUS[2]) {
723  $status = UploadStatus::CLOSED;
724  } elseif ($newStatus == self::VALID_STATUS[3]) {
725  $status = UploadStatus::REJECTED;
726  } else {
727  $status = UploadStatus::OPEN;
728  }
729  $uploadBrowseProxy->setStatusAndComment($id, $status, $comment);
730  }
731  // Handle update of name
732  if (
733  $isJsonRequest &&
734  array_key_exists(self::FILTER_NAME, $bodyContent) &&
735  strlen(trim($bodyContent[self::FILTER_NAME])) > 0
736  ) {
737  $newName = trim($bodyContent[self::FILTER_NAME]);
738  }
739  // Handle update of description
740  if (
741  $isJsonRequest &&
742  array_key_exists("uploadDescription", $bodyContent) &&
743  strlen(trim($bodyContent["uploadDescription"])) > 0
744  ) {
745  $newDescription = trim($bodyContent["uploadDescription"]);
746  }
747  if ($newName != null || $newDescription != null) {
749  $uploadProperties = $this->restHelper->getPlugin('upload_properties');
750  $updated = $uploadProperties->UpdateUploadProperties($id, $newName, $newDescription);
751  if ($updated == 2) {
752  throw new HttpBadRequestException("Invalid request to update upload name and description.");
753  }
754  }
755 
756  $returnVal = new Info(202, "Upload updated successfully.", InfoType::INFO);
757  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
758  }
759 
765  private function isAdj2nestDone($id): void
766  {
767  $itemTreeBounds = $this->restHelper->getUploadDao()->getParentItemBounds(
768  $id);
769  if ($itemTreeBounds === false || empty($itemTreeBounds->getLeft())) {
771  "Ununpack job not started. Please check job status at " .
772  "/api/v1/jobs?upload=" . $id))
773  ->setHeaders(['Retry-After' => '60',
774  'Look-at' => "/api/v1/jobs?upload=" . $id]);
775  }
776  }
777 
787  private function areAgentsScheduled($uploadId, $agents, $response): void
788  {
789  global $container;
790  $agentDao = $container->get('dao.agent');
791 
792  $agentList = array_keys(AgentRef::AGENT_LIST);
793  $intersectArray = array_intersect($agents, $agentList);
794 
795  if (count($agents) != count($intersectArray)) {
796  throw new HttpBadRequestException("Agent should be any of " .
797  implode(", ", $agentList) . ". " . implode(",", $agents) . " passed.");
798  } else {
799  // Agent is valid, check if they have ars tables.
800  foreach ($agents as $agent) {
801  if (! $agentDao->arsTableExists($agent)) {
803  "Agent $agent not scheduled for the upload. " .
804  "Please POST to /jobs");
805  }
806  }
807  }
808 
809  $scanProxy = new ScanJobProxy($agentDao, $uploadId);
810  $agentList = $scanProxy->createAgentStatus($agents);
811 
812  foreach ($agentList as $agent) {
813  if (! array_key_exists('currentAgentId', $agent)) {
815  "Agent " . $agent["agentName"] .
816  " not scheduled for the upload. Please POST to /jobs");
817  }
818  if (array_key_exists('isAgentRunning', $agent) &&
819  $agent['isAgentRunning']) {
821  "Agent " . $agent["agentName"] . " is running. " .
822  "Please check job status at /api/v1/jobs?upload=" . $uploadId))
823  ->setHeaders(['Retry-After' => '60',
824  'Look-at' => "/api/v1/jobs?upload=" . $uploadId]);
825  }
826  }
827  }
828 
838  public function setUploadPermissions($request, $response, $args)
839  {
840  $returnVal = null;
841  // checking if the scheduler is running or not
842  $commu_status = fo_communicate_with_scheduler('status', $response_from_scheduler, $error_info);
843  if (!$commu_status) {
844  throw new HttpServiceUnavailableException("Scheduler is not running!");
845  }
846  // Initialising upload-permissions plugin
847  global $container;
848  $restHelper = $container->get('helper.restHelper');
849  $uploadPermissionObj = $restHelper->getPlugin('upload_permissions');
850 
851  $dbManager = $this->dbHelper->getDbManager();
852  // parsing the request body
853  $reqBody = $this->getParsedBody($request);
854 
855  $folder_pk = intval($reqBody['folderId']);
856  $upload_pk = intval($args['id']);
857  $this->uploadAccessible($upload_pk);
858  $allUploadsPerm = $reqBody['allUploadsPermission'] ? 1 : 0;
859  $newgroup = intval($reqBody['groupId']);
860  $newperm = $this->getEquivalentValueForPermission($reqBody['newPermission']);
861  $public_perm = isset($reqBody['publicPermission']) ? $this->getEquivalentValueForPermission($reqBody['publicPermission']) : -1;
862 
863  $query = "SELECT perm, perm_upload_pk FROM perm_upload WHERE upload_fk=$1 and group_fk=$2;";
864  $result = $dbManager->getSingleRow($query, [$upload_pk, $newgroup], __METHOD__.".getOldPerm");
865  $perm_upload_pk = 0;
866  $perm = 0;
867  if (!empty($result)) {
868  $perm_upload_pk = intVal($result['perm_upload_pk']);
869  $perm = $newperm;
870  }
871 
872  $uploadPermissionObj->editPermissionsForUpload($commu_status, $folder_pk, $upload_pk, $allUploadsPerm, $perm_upload_pk, $perm, $newgroup, $newperm, $public_perm);
873 
874  $returnVal = new Info(202, "Permissions updated successfully!", InfoType::INFO);
875  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
876  }
877 
878  public function getEquivalentValueForPermission($perm)
879  {
880  switch ($perm) {
881  case 'read_only':
882  return Auth::PERM_READ;
883  case 'read_write':
884  return Auth::PERM_WRITE;
885  case 'clearing_admin':
886  return Auth::PERM_CADMIN;
887  case 'admin':
888  return Auth::PERM_ADMIN;
889  default:
890  return Auth::PERM_NONE;
891  }
892  }
893 
903  public function getGroupsWithPermissions($request, $response, $args)
904  {
905  $apiVersion = ApiVersion::getVersion($request);
906  $upload_pk = intval($args['id']);
907  $this->uploadAccessible($upload_pk);
908  $publicPerm = $this->restHelper->getUploadPermissionDao()->getPublicPermission($upload_pk);
909  $permGroups = $this->restHelper->getUploadPermissionDao()->getPermissionGroups($upload_pk);
910 
911  // Removing the perm_upload_pk parameter in response
912  $finalPermGroups = [];
913  foreach ($permGroups as $value) {
914  $groupPerm = new GroupPermission($value['perm'], $value['group_pk'], $value['group_name']);
915  $finalPermGroups[] = $groupPerm->getArray($apiVersion);
916  }
917  $res = new Permissions($publicPerm, $finalPermGroups);
918  return $response->withJson($res->getArray($apiVersion), 200);
919  }
920 
930  public function getMainLicenses($request, $response, $args)
931  {
932  $uploadId = intval($args['id']);
933  $this->uploadAccessible($uploadId);
934 
936  $clearingDao = $this->container->get('dao.clearing');
937  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
938  $licenseDao = $this->container->get('dao.license');
939  $licenses = array();
940 
941  foreach ($licenseIds as $value) {
942  $licenseId = intval($value);
943  $obligations = $licenseDao->getLicenseObligations([$licenseId],
944  false);
945  $obligations = array_merge($obligations,
946  $licenseDao->getLicenseObligations([$licenseId], true));
947  $obligationList = [];
948  foreach ($obligations as $obligation) {
949  $obligationList[] = new Obligation(
950  $obligation['ob_pk'],
951  $obligation['ob_topic'],
952  $obligation['ob_type'],
953  $obligation['ob_text'],
954  $obligation['ob_classification'],
955  $obligation['ob_comment']
956  );
957  }
958  $license = $licenseDao->getLicenseById($licenseId);
959  $licenseObj = new License(
960  $license->getId(),
961  $license->getShortName(),
962  $license->getFullName(),
963  $license->getText(),
964  $license->getUrl(),
965  $obligationList,
966  $license->getRisk()
967  );
968  $licenses[] = $licenseObj->getArray();
969  }
970  return $response->withJson($licenses, 200);
971  }
972 
982  public function setMainLicense($request, $response, $args)
983  {
984  $uploadId = intval($args['id']);
985  $body = $this->getParsedBody($request);
986  $shortName = $body['shortName'];
987  $licenseDao = $this->container->get('dao.license');
988  $clearingDao = $this->container->get('dao.clearing');
989 
990  $this->uploadAccessible($uploadId);
991 
992  if (empty($shortName)) {
993  throw new HttpBadRequestException("Short name missing from request.");
994  }
995  $license = $licenseDao->getLicenseByShortName($shortName,
996  $this->restHelper->getGroupId());
997 
998  if ($license === null) {
999  throw new HttpNotFoundException(
1000  "No license with shortname '$shortName' found.");
1001  }
1002 
1003  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1004  if (in_array($license->getId(), $licenseIds)) {
1005  throw new HttpBadRequestException(
1006  "License already exists for this upload.");
1007  }
1008 
1010  $clearingDao = $this->container->get('dao.clearing');
1011  $clearingDao->makeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1012  $returnVal = new Info(200, "Successfully added new main license", InfoType::INFO);
1013  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1014  }
1015 
1016  /***
1017  * Remove the main license from the upload
1018  *
1019  * @param ServerRequestInterface $request
1020  * @param ResponseHelper $response
1021  * @param array $args
1022  * @return ResponseHelper
1023  * @throws HttpErrorException
1024  */
1025  public function removeMainLicense($request, $response, $args)
1026  {
1027  $uploadId = intval($args['id']);
1028  $shortName = $args['shortName'];
1029  $licenseDao = $this->container->get('dao.license');
1030  $clearingDao = $this->container->get('dao.clearing');
1031  $license = $licenseDao->getLicenseByShortName($shortName, $this->restHelper->getGroupId());
1032 
1033  $this->uploadAccessible($uploadId);
1034 
1035  if ($license === null) {
1036  throw new HttpNotFoundException(
1037  "No license with shortname '$shortName' found.");
1038  }
1039  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1040  if (!in_array($license->getId(), $licenseIds)) {
1041  throw new HttpBadRequestException(
1042  "License '$shortName' is not a main license for this upload.");
1043  }
1044 
1045  $clearingDao = $this->container->get('dao.clearing');
1046  $clearingDao->removeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1047  $returnVal = new Info(200, "Main license removed successfully.", InfoType::INFO);
1048 
1049  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1050  }
1051 
1061  public function getClearingProgressInfo($request, $response, $args)
1062  {
1063  $uploadId = intval($args['id']);
1064  $uploadDao = $this->restHelper->getUploadDao();
1065 
1066  $this->uploadAccessible($uploadId);
1067 
1068  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1069 
1070  $noLicenseUploadTreeView = new UploadTreeProxy($uploadId,
1071  array(UploadTreeProxy::OPT_SKIP_THESE => "noLicense",
1072  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1073  $uploadTreeTableName,
1074  'no_license_uploadtree' . $uploadId);
1075 
1076  $filesOfInterest = $noLicenseUploadTreeView->count();
1077 
1078  $nonClearedUploadTreeView = new UploadTreeProxy($uploadId,
1079  array(UploadTreeProxy::OPT_SKIP_THESE => "alreadyCleared",
1080  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1081  $uploadTreeTableName,
1082  'already_cleared_uploadtree' . $uploadId);
1083  $filesToBeCleared = $nonClearedUploadTreeView->count();
1084 
1085  $filesAlreadyCleared = $filesOfInterest - $filesToBeCleared;
1086 
1087  $res = [
1088  "totalFilesOfInterest" => intval($filesOfInterest),
1089  "totalFilesCleared" => intval($filesAlreadyCleared),
1090  ];
1091  return $response->withJson($res, 200);
1092  }
1093 
1103  public function getLicensesHistogram($request, $response, $args)
1104  {
1105  $agentDao = $this->container->get('dao.agent');
1106  $clearingDao = $this->container->get('dao.clearing');
1107  $licenseDao = $this->container->get('dao.license');
1108 
1109  $uploadId = intval($args['id']);
1110  $uploadDao = $this->restHelper->getUploadDao();
1111  $query = $request->getQueryParams();
1112  $selectedAgentId = $query['agentId'] ?? null;
1113 
1114  $this->uploadAccessible($uploadId);
1115 
1116  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1117  throw new HttpNotFoundException("Agent does not exist.");
1118  }
1119 
1120  $scannerAgents = array_keys($this->agentNames);
1121  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1122  $scanJobProxy->createAgentStatus($scannerAgents);
1123  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1124  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1125  $editedLicenses = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1126  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1127  $scannedLicenses = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1128  $allScannerLicenseNames = array_keys($scannedLicenses);
1129  $allEditedLicenseNames = array_keys($editedLicenses);
1130  $allLicNames = array_unique(array_merge($allScannerLicenseNames, $allEditedLicenseNames));
1131  $realLicNames = array_diff($allLicNames, array(LicenseDao::NO_LICENSE_FOUND));
1132  $totalScannerLicenseCount = 0;
1133  $editedTotalLicenseCount = 0;
1134 
1135  $res = array();
1136  foreach ($realLicNames as $licenseShortName) {
1137  $count = 0;
1138  if (array_key_exists($licenseShortName, $scannedLicenses)) {
1139  $count = $scannedLicenses[$licenseShortName]['unique'];
1140  $rfId = $scannedLicenses[$licenseShortName]['rf_pk'];
1141  } else {
1142  $rfId = $editedLicenses[$licenseShortName]['rf_pk'];
1143  }
1144  $editedCount = array_key_exists($licenseShortName, $editedLicenses) ? $editedLicenses[$licenseShortName]['count'] : 0;
1145  $totalScannerLicenseCount += $count;
1146  $editedTotalLicenseCount += $editedCount;
1147  $scannerCountLink = $count;
1148  $editedLink = $editedCount;
1149 
1150  $res[] = array($scannerCountLink, $editedLink, array($licenseShortName, $rfId));
1151  }
1152 
1153  $outputArray = [];
1154 
1155  foreach ($res as $item) {
1156  $outputArray[] = [
1157  "id" => intval($item[2][1]),
1158  "name" => $item[2][0],
1159  "scannerCount" => intval($item[0]),
1160  "concludedCount" => intval($item[1]),
1161  ];
1162  }
1163  return $response->withJson($outputArray, 200);
1164  }
1165 
1175  public function getAllAgents($request, $response, $args)
1176  {
1177  $uploadId = intval($args['id']);
1178 
1179  $this->uploadAccessible($uploadId);
1180 
1181  $scannerAgents = array_keys($this->agentNames);
1182  $agentDao = $this->container->get('dao.agent');
1183  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1184  $res = $scanJobProxy->createAgentStatus($scannerAgents);
1185 
1186  $outputArray = [];
1187  foreach ($res as &$item) {
1188  $successfulAgents = [];
1189  if (count($item['successfulAgents']) > 0) {
1190  $item['isAgentRunning'] = false;
1191  } else {
1192  $item['currentAgentId'] = $agentDao->getCurrentAgentRef($item["agentName"])->getAgentId();
1193  $item['currentAgentRev'] = "";
1194  }
1195  foreach ($item['successfulAgents'] as &$agent) {
1196  $successfulAgent = new SuccessfulAgent(intval($agent['agent_id']), $agent['agent_rev'], $agent['agent_name']);
1197  $successfulAgents[] = $successfulAgent->getArray(ApiVersion::getVersion($request));
1198  }
1199  $agent = new Agent($successfulAgents, $item['uploadId'], $item['agentName'], $item['currentAgentId'], $item['currentAgentRev'], $item['isAgentRunning']);
1200  $outputArray[] = $agent->getArray(ApiVersion::getVersion($request));
1201  }
1202  return $response->withJson($outputArray, 200);
1203  }
1204 
1214  public function getEditedLicenses($request, $response, $args)
1215  {
1216  $uploadId = intval($args['id']);
1217 
1218  $this->uploadAccessible($uploadId);
1219 
1220  $clearingDao = $this->container->get('dao.clearing');
1221  $uploadDao = $this->restHelper->getUploadDao();
1222  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1223  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1224  $res = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1225  $outputArray = [];
1226 
1227  foreach ($res as $key => $value) {
1228  $editedLicense = new EditedLicense(intval($value["rf_pk"]), $key, intval($value["count"]), $value["spdx_id"]);
1229  $outputArray[] = $editedLicense->getArray(ApiVersion::getVersion($request));
1230  }
1231  return $response->withJson($outputArray, 200);
1232  }
1233 
1243  public function getReuseReportSummary($request, $response, $args)
1244  {
1245  $uploadId = intval($args['id']);
1246  $this->uploadAccessible($uploadId);
1247 
1249  $reuseReportProcess = $this->container->get('businessrules.reusereportprocessor');
1250  $res = $reuseReportProcess->getReuseSummary($uploadId);
1251  return $response->withJson($res, 200);
1252  }
1253 
1263  public function getScannedLicenses($request, $response, $args)
1264  {
1265  $uploadId = intval($args['id']);
1266  $query = $request->getQueryParams();
1267  $selectedAgentId = $query['agentId'] ?? null;
1268  $licenseDao = $this->container->get('dao.license');
1269 
1270  $this->uploadAccessible($uploadId);
1271  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1272  throw new HttpNotFoundException("Agent does not exist.");
1273  }
1274  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
1275  $scanJobProxy = new ScanJobProxy($this->agentDao, $uploadId);
1276  $scanJobProxy->createAgentStatus($scannerAgents);
1277  $uploadDao = $this->restHelper->getUploadDao();
1278  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1279  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1280  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1281  $res = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1282  $outputArray = [];
1283 
1284  foreach ($res as $key => $value) {
1285  $scannedLicense = new ScannedLicense(
1286  $value['rf_pk'],
1287  $key,
1288  $value['count'],
1289  $value['unique'],
1290  $value['spdx_id']
1291  );
1292  $outputArray[] = $scannedLicense->getArray(ApiVersion::getVersion($request));
1293  }
1294  return $response->withJson($outputArray, 200);
1295  }
1305  public function getAgentsRevision($request, $response, $args)
1306  {
1307  $agentDao = $this->container->get('dao.agent');
1308  $uploadId = intval($args['id']);
1309 
1310  $this->uploadAccessible($uploadId);
1311 
1312  $scannerAgents = array_keys($this->agentNames);
1313  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1314  $scanJobProxy->createAgentStatus($scannerAgents);
1315 
1316  $res = array();
1317  foreach ($scanJobProxy->getSuccessfulAgents() as $agent) {
1318  $res[] = array(
1319  "id" => $agent->getAgentId(),
1320  "name" => $agent->getAgentName(),
1321  "revision" => $agent->getAgentRevision(),
1322  );
1323  }
1324  return $response->withJson($res, 200);
1325  }
1326 
1336  public function getTopItem($request, $response, $args)
1337  {
1338  $uploadId = intval($args['id']);
1339  if (!$this->dbHelper->doesIdExist("upload", "upload_pk", $uploadId)) {
1340  $returnVal = new Info(404, "Upload does not exist", InfoType::ERROR);
1341  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1342  }
1343  $uploadDao = $this->restHelper->getUploadDao();
1344  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId,
1345  $uploadDao->getUploadtreeTableName($uploadId));
1346  if ($itemTreeBounds === false) {
1347  $error = new Info(500, "Unable to get top item.", InfoType::ERROR);
1348  return $response->withJson($error->getArray(), $error->getCode());
1349  }
1350  $info = new Info(200, $itemTreeBounds->getItemId(), InfoType::INFO);
1351  return $response->withJson($info->getArray(), $info->getCode());
1352  }
1353 }
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