FOSSology  4.5.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 
8  SPDX-License-Identifier: GPL-2.0-only
9 */
10 
16 namespace Fossology\UI\Api\Controllers;
17 
50 use Psr\Http\Message\ServerRequestInterface;
51 use Slim\Psr7\Factory\StreamFactory;
52 
58 {
59 
63  const AGENT_PARAM = "agent";
64 
68  const FOLDER_PARAM = "folderId";
69 
73  const RECURSIVE_PARAM = "recursive";
74 
78  const FILTER_NAME = "name";
79 
83  const FILTER_STATUS = "status";
84 
88  const FILTER_ASSIGNEE = "assignee";
89 
93  const FILTER_DATE = "since";
94 
98  const PAGE_PARAM = "page";
99 
103  const LIMIT_PARAM = "limit";
104 
108  const UPLOAD_FETCH_LIMIT = 100;
109 
113  const CONTAINER_PARAM = "containers";
114 
118  const VALID_STATUS = ["open", "inprogress", "closed", "rejected"];
119 
123  private $agentNames = AgentRef::AGENT_LIST;
124 
129  private $agentDao;
130 
131  public function __construct($container)
132  {
133  parent::__construct($container);
134  $groupId = $this->restHelper->getGroupId();
135  $dbManager = $this->dbHelper->getDbManager();
136  $this->agentDao = $this->container->get('dao.agent');
137  $uploadBrowseProxy = new UploadBrowseProxy($groupId, 0, $dbManager, false);
138  $uploadBrowseProxy->sanity();
139  }
140 
150  public function getUploads($request, $response, $args)
151  {
152  $id = null;
153  $folderId = null;
154  $recursive = true;
155  $query = $request->getQueryParams();
156  $name = null;
157  $status = null;
158  $assignee = null;
159  $since = null;
160  $apiVersion = ApiVersion::getVersion($request);
161 
162  if (array_key_exists(self::FOLDER_PARAM, $query)) {
163  $folderId = filter_var($query[self::FOLDER_PARAM], FILTER_VALIDATE_INT);
164  if (! $this->restHelper->getFolderDao()->isFolderAccessible($folderId,
165  $this->restHelper->getUserId())) {
166  throw new HttpNotFoundException("Folder does not exist");
167  }
168  }
169 
170  if (array_key_exists(self::RECURSIVE_PARAM, $query)) {
171  $recursive = filter_var($query[self::RECURSIVE_PARAM],
172  FILTER_VALIDATE_BOOLEAN);
173  }
174  if (array_key_exists(self::FILTER_NAME, $query)) {
175  $name = $query[self::FILTER_NAME];
176  }
177  if (array_key_exists(self::FILTER_STATUS, $query)) {
178  switch (strtolower($query[self::FILTER_STATUS])) {
179  case "open":
180  $status = UploadStatus::OPEN;
181  break;
182  case "inprogress":
183  $status = UploadStatus::IN_PROGRESS;
184  break;
185  case "closed":
186  $status = UploadStatus::CLOSED;
187  break;
188  case "rejected":
189  $status = UploadStatus::REJECTED;
190  break;
191  default:
192  $status = null;
193  }
194  }
195  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
196  $username = $query[self::FILTER_ASSIGNEE];
197  if (strcasecmp($username, "-me-") === 0) {
198  $assignee = $this->restHelper->getUserId();
199  } elseif (strcasecmp($username, "-unassigned-") === 0) {
200  $assignee = 1;
201  } else {
202  $assignee = $this->restHelper->getUserDao()->getUserByName($username);
203  if (empty($assignee)) {
204  throw new HttpNotFoundException("No user with user name '$username'");
205  }
206  $assignee = $assignee['user_pk'];
207  }
208  }
209  if (array_key_exists(self::FILTER_DATE, $query)) {
210  $date = filter_var($query[self::FILTER_DATE], FILTER_VALIDATE_REGEXP,
211  ["options" => [
212  "regexp" => "/^\d{4}\-\d{2}\-\d{2}$/",
213  "flags" => FILTER_NULL_ON_FAILURE
214  ]]);
215  $since = strtotime($date);
216  }
217  if ($apiVersion == ApiVersion::V2) {
218  $page = $query[self::PAGE_PARAM] ?? "";
219  $limit = $query[self::LIMIT_PARAM] ?? "";
220  } else {
221  $page = $request->getHeaderLine(self::PAGE_PARAM);
222  $limit = $request->getHeaderLine(self::LIMIT_PARAM);
223  }
224  if (! empty($page) || $page == "0") {
225  $page = filter_var($page, FILTER_VALIDATE_INT);
226  if ($page <= 0) {
227  throw new HttpBadRequestException(
228  "page should be positive integer > 0");
229  }
230  } else {
231  $page = 1;
232  }
233  if (! empty($limit)) {
234  $limit = filter_var($limit, FILTER_VALIDATE_INT);
235  if ($limit < 1) {
236  throw new HttpBadRequestException(
237  "limit should be positive integer > 1");
238  }
239  } else {
240  $limit = self::UPLOAD_FETCH_LIMIT;
241  }
242 
243  if (isset($args['id'])) {
244  $id = intval($args['id']);
245  $this->uploadAccessible($id);
246  $this->isAdj2nestDone($id);
247  }
248  $options = [
249  "folderId" => $folderId,
250  "name" => $name,
251  "status" => $status,
252  "assignee" => $assignee,
253  "since" => $since
254  ];
255  list($pages, $uploads) = $this->dbHelper->getUploads(
256  $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $limit,
257  $page, $id, $options, $recursive, $apiVersion);
258  if ($id !== null && ! empty($uploads)) {
259  $uploads = $uploads[0];
260  $pages = 1;
261  }
262  return $response->withHeader("X-Total-Pages", $pages)->withJson($uploads,
263  200);
264  }
265 
275  public function uploadDownload($request, $response, $args)
276  {
278  $ui_download = $this->restHelper->getPlugin('download');
279  $id = null;
280 
281  if (isset($args['id'])) {
282  $id = intval($args['id']);
283  $this->uploadAccessible($id);
284  }
285  $dbManager = $this->restHelper->getDbHelper()->getDbManager();
286  $uploadDao = $this->restHelper->getUploadDao();
287  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
288  $itemTreeBounds = $uploadDao->getParentItemBounds($id,$uploadTreeTableName);
289  $sql = "SELECT pfile_fk , ufile_name FROM uploadtree_a WHERE uploadtree_pk=$1";
290  $params = array($itemTreeBounds->getItemId());
291  $descendants = $dbManager->getSingleRow($sql,$params);
292  $path= RepPath(($descendants['pfile_fk']));
293  $responseFile = $ui_download->getDownload($path, $descendants['ufile_name']);
294  $responseContent = $responseFile->getFile();
295  $newResponse = $response->withHeader('Content-Description',
296  'File Transfer')
297  ->withHeader('Content-Type',
298  $responseContent->getMimeType())
299  ->withHeader('Content-Disposition',
300  $responseFile->headers->get('Content-Disposition'))
301  ->withHeader('Cache-Control', 'must-revalidate')
302  ->withHeader('Pragma', 'private')
303  ->withHeader('Content-Length', filesize($responseContent->getPathname()));
304  $sf = new StreamFactory();
305  return $newResponse->withBody(
306  $sf->createStreamFromFile($responseContent->getPathname())
307  );
308  }
309 
319  public function getUploadSummary($request, $response, $args)
320  {
321  $id = intval($args['id']);
322  $query = $request->getQueryParams();
323  $selectedAgentId = $query['agentId'] ?? null;
324  $agentDao = $this->container->get('dao.agent');
325  $this->uploadAccessible($id);
326  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
327  throw new HttpNotFoundException("Agent does not exist");
328  }
329  $this->isAdj2nestDone($id);
330  $uploadHelper = new UploadHelper();
331  $uploadSummary = $uploadHelper->generateUploadSummary($id, $this->restHelper->getGroupId());
332  $browseLicense = $this->restHelper->getPlugin('license');
333  $uploadDao = $this->restHelper->getUploadDao();
334  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($id);
335  $itemTreeBounds = $uploadDao->getParentItemBounds($id, $uploadTreeTableName);
336  $scanJobProxy = new ScanJobProxy($agentDao, $id);
337  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
338  $scanJobProxy->createAgentStatus($scannerAgents);
339  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
340  $res = $browseLicense->createLicenseHistogram("", "", $itemTreeBounds, $selectedAgentIds, $this->restHelper->getGroupId());
341  $uploadSummary->setUniqueConcludedLicenses($res['editedUniqueLicenseCount']);
342  $uploadSummary->setTotalConcludedLicenses($res['editedLicenseCount']);
343  $uploadSummary->setTotalLicenses($res['scannerLicenseCount']);
344  $uploadSummary->setUniqueLicenses($res['uniqueLicenseCount']);
345  $uploadSummary->setConcludedNoLicenseFoundCount($res['editedNoLicenseFoundCount']);
346  $uploadSummary->setFileCount($res['fileCount']);
347  $uploadSummary->setNoScannerLicenseFoundCount($res['noScannerLicenseFoundCount']);
348  $uploadSummary->setScannerUniqueLicenseCount($res['scannerUniqueLicenseCount']);
349 
350  return $response->withJson($uploadSummary->getArray(), 200);
351  }
352 
362  public function deleteUpload($request, $response, $args)
363  {
364  require_once dirname(__DIR__, 4) . "/delagent/ui/delete-helper.php";
365  $id = intval($args['id']);
366 
367  $this->uploadAccessible($id);
368  $result = TryToDelete($id, $this->restHelper->getUserId(),
369  $this->restHelper->getGroupId(), $this->restHelper->getUploadDao());
370  if ($result->getDeleteMessageCode() !== DeleteMessages::SUCCESS) {
372  $result->getDeleteMessageString());
373  }
374  $returnVal = new Info(202, "Delete Job for file with id " . $id,
375  InfoType::INFO);
376  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
377  }
378 
387  public function moveUpload($request, $response, $args)
388  {
389  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
390  $queryParams = $request->getQueryParams();
391  $action = $queryParams['action'] ?? "";
392  } else {
393  $action = $request->getHeaderLine('action');
394  }
395  if (strtolower($action) == "move") {
396  $copy = false;
397  } else {
398  $copy = true;
399  }
400  return $this->changeUpload($request, $response, $args, $copy);
401  }
402 
413  private function changeUpload($request, $response, $args, $isCopy)
414  {
415  $queryParams = $request->getQueryParams();
416  $isApiVersionV2 = (ApiVersion::getVersion($request) == ApiVersion::V2);
417  $paramType = ($isApiVersionV2) ? 'parameter' : 'header';
418 
419  if ((!$isApiVersionV2 && !$request->hasHeader('folderId') || $isApiVersionV2 && !isset($queryParams['folderId']))
420  || !is_numeric($newFolderID = ($isApiVersionV2 ? $queryParams['folderId'] : $request->getHeaderLine('folderId')))) {
421  throw new HttpBadRequestException("For API version " . ($isApiVersionV2 ? 'V2' : 'V1') . ", 'folderId' $paramType should be present and an integer.");
422  }
423 
424  $id = intval($args['id']);
425  $returnVal = $this->restHelper->copyUpload($id, $newFolderID, $isCopy);
426  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
427  }
428 
438  public function postUpload($request, $response, $args)
439  {
440  $reqBody = $this->getParsedBody($request);
441  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
442  $uploadType = $reqBody['uploadType'] ?? null;
443  $folderId = $reqBody['folderId'] ?? null;
444  $description = $reqBody['uploadDescription'] ?? "";
445  $public = $reqBody['public'] ?? null;
446  $applyGlobal = filter_var($reqBody['applyGlobal'] ?? null,
447  FILTER_VALIDATE_BOOLEAN);
448  $ignoreScm = $reqBody['ignoreScm'] ?? null;
449  } else {
450  $uploadType = $request->getHeaderLine('uploadType');
451  $folderId = $request->getHeaderLine('folderId');
452  $description = $request->getHeaderLine('uploadDescription');
453  $public = $request->getHeaderLine('public');
454  $applyGlobal = filter_var($request->getHeaderLine('applyGlobal'),
455  FILTER_VALIDATE_BOOLEAN);
456  $ignoreScm = $request->getHeaderLine('ignoreScm');
457  }
458 
459  $public = empty($public) ? 'protected' : $public;
460 
461  if (empty($uploadType)) {
462  throw new HttpBadRequestException("Require uploadType");
463  }
464  $scanOptions = [];
465  if (array_key_exists('scanOptions', $reqBody)) {
466  if ($uploadType == 'file') {
467  $scanOptions = json_decode($reqBody['scanOptions'], true);
468  } else {
469  $scanOptions = $reqBody['scanOptions'];
470  }
471  }
472 
473  if (! is_array($scanOptions)) {
474  $scanOptions = [];
475  }
476 
477  $uploadHelper = new UploadHelper();
478 
479  if ($uploadType != "file" && (empty($reqBody) ||
480  ! array_key_exists("location", $reqBody))) {
481  throw new HttpBadRequestException(
482  "Require location object if uploadType != file");
483  }
484  if (empty($folderId) ||
485  !is_numeric($folderId) && $folderId > 0) {
486  throw new HttpBadRequestException("folderId must be a positive integer!");
487  }
488 
489  $allFolderIds = $this->restHelper->getFolderDao()->getAllFolderIds();
490  if (!in_array($folderId, $allFolderIds)) {
491  throw new HttpNotFoundException("folderId $folderId does not exists!");
492  }
493  if (!$this->restHelper->getFolderDao()->isFolderAccessible($folderId)) {
494  throw new HttpForbiddenException("folderId $folderId is not accessible!");
495  }
496 
497  $locationObject = [];
498  if (array_key_exists("location", $reqBody)) {
499  $locationObject = $reqBody["location"];
500  } elseif ($uploadType != 'file') {
501  throw new HttpBadRequestException(
502  "Require location object if uploadType != file");
503  }
504 
505  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
506  $folderId, $description, $public, $ignoreScm, $uploadType,
507  $applyGlobal);
508  $status = $uploadResponse[0];
509  $message = $uploadResponse[1];
510  $statusDescription = $uploadResponse[2];
511  if (! $status) {
512  throw new HttpInternalServerErrorException($message . "\n" .
513  $statusDescription);
514  }
515 
516  $uploadId = $uploadResponse[3];
517  if (! empty($scanOptions)) {
518  $info = $uploadHelper->handleScheduleAnalysis(intval($uploadId),
519  intval($folderId), $scanOptions, true);
520  if ($info->getCode() == 201) {
521  $info = new Info($info->getCode(), intval($uploadId), $info->getType());
522  }
523  } else {
524  $info = new Info(201, intval($uploadId), InfoType::INFO);
525  }
526  if (array_key_exists("mainLicense", $reqBody) &&
527  ! empty($reqBody["mainLicense"])) {
528  global $container;
530  $licenseDao = $container->get('dao.license');
531  $mainLicense = $licenseDao
532  ->getLicenseByShortName($reqBody["mainLicense"]);
533  if ($mainLicense !== null) {
535  $clearingDao = $container->get('dao.clearing');
536  $clearingDao->makeMainLicense($uploadId,
537  $this->restHelper->getGroupId(), $mainLicense->getId());
538  }
539  }
540  return $response->withJson($info->getArray(), $info->getCode());
541  }
542 
552  public function getUploadLicenses($request, $response, $args)
553  {
554  $id = intval($args['id']);
555  $query = $request->getQueryParams();
556  $apiVersion = ApiVersion::getVersion($request);
557  if ($apiVersion == ApiVersion::V2) {
558  $page = $query['page'] ?? "";
559  $limit = $query['limit'] ?? "";
560  } else {
561  $page = $request->getHeaderLine("page");
562  $limit = $request->getHeaderLine("limit");
563  }
564  if (! array_key_exists(self::AGENT_PARAM, $query)) {
565  throw new HttpBadRequestException("agent parameter missing from query.");
566  }
567  $agents = explode(",", $query[self::AGENT_PARAM]);
568  $containers = true;
569  if (array_key_exists(self::CONTAINER_PARAM, $query)) {
570  $containers = (strcasecmp($query[self::CONTAINER_PARAM], "true") === 0);
571  }
572 
573  $license = true;
574  if (array_key_exists('license', $query)) {
575  $license = (strcasecmp($query['license'], "true") === 0);
576  }
577 
578  $copyright = false;
579  if (array_key_exists('copyright', $query)) {
580  $copyright = (strcasecmp($query['copyright'], "true") === 0);
581  }
582 
583  if (!$license && !$copyright) {
584  throw new HttpBadRequestException(
585  "'license' and 'copyright' atleast one should be true.");
586  }
587 
588  $this->uploadAccessible($id);
589  $this->isAdj2nestDone($id);
590 
591  $this->areAgentsScheduled($id, $agents, $response);
592 
593  /*
594  * check if page && limit are numeric, if existing
595  */
596  if ((! ($page==='') && (! is_numeric($page) || $page < 1)) ||
597  (! ($limit==='') && (! is_numeric($limit) || $limit < 1))) {
598  throw new HttpBadRequestException(
599  "page and limit need to be positive integers!");
600  }
601 
602  // set page to 1 by default
603  if (empty($page)) {
604  $page = 1;
605  }
606 
607  // set limit to 50 by default and max as 1000
608  if (empty($limit)) {
609  $limit = 50;
610  } else if ($limit > 1000) {
611  $limit = 1000;
612  }
613 
614  $uploadHelper = new UploadHelper();
615  list($licenseList, $count) = $uploadHelper->getUploadLicenseList($id, $agents, $containers, $license, $copyright, $page-1, $limit, $apiVersion);
616  $totalPages = intval(ceil($count / $limit));
617  return $response->withHeader("X-Total-Pages", $totalPages)->withJson($licenseList, 200);
618  }
619 
629  public function getUploadCopyrights($request, $response, $args)
630  {
631  $id = intval($args['id']);
632  $this->uploadAccessible($id);
633  $this->isAdj2nestDone($id);
634  $uploadHelper = new UploadHelper();
635  $licenseList = $uploadHelper->getUploadCopyrightList($id);
636  return $response->withJson($licenseList, 200);
637  }
638 
648  public function updateUpload($request, $response, $args)
649  {
650  $id = intval($args['id']);
651  $query = $request->getQueryParams();
652  $userDao = $this->restHelper->getUserDao();
653  $userId = $this->restHelper->getUserId();
654  $groupId = $this->restHelper->getGroupId();
655  $isJsonRequest = $this->isJsonRequest($request);
656 
657  $perm = $userDao->isAdvisorOrAdmin($userId, $groupId);
658  if (!$perm) {
659  throw new HttpForbiddenException("Not advisor or admin of current group. " .
660  "Can not update upload.");
661  }
662  $uploadBrowseProxy = new UploadBrowseProxy(
663  $groupId,
664  $perm,
665  $this->dbHelper->getDbManager()
666  );
667 
668  $assignee = null;
669  $status = null;
670  $comment = null;
671  $newName = null;
672  $newDescription = null;
673 
674  if ($isJsonRequest) {
675  $bodyContent = $this->getParsedBody($request);
676  } else {
677  $body = $request->getBody();
678  $bodyContent = $body->getContents();
679  $body->close();
680  }
681 
682  // Handle assignee info
683  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
684  $assignee = filter_var($query[self::FILTER_ASSIGNEE], FILTER_VALIDATE_INT);
685  $userList = $userDao->getUserChoices($groupId);
686  if (!array_key_exists($assignee, $userList)) {
687  throw new HttpNotFoundException(
688  "New assignee does not have permission on upload.");
689  }
690  $uploadBrowseProxy->updateTable("assignee", $id, $assignee);
691  }
692  // Handle new status
693  if (
694  array_key_exists(self::FILTER_STATUS, $query) &&
695  in_array(strtolower($query[self::FILTER_STATUS]), self::VALID_STATUS)
696  ) {
697  $newStatus = strtolower($query[self::FILTER_STATUS]);
698  $comment = '';
699  if (in_array($newStatus, ["closed", "rejected"])) {
700  if ($isJsonRequest && array_key_exists("comment", $bodyContent)) {
701  $comment = $bodyContent["comment"];
702  } else {
703  $comment = $bodyContent;
704  }
705  }
706  $status = 0;
707  if ($newStatus == self::VALID_STATUS[1]) {
708  $status = UploadStatus::IN_PROGRESS;
709  } elseif ($newStatus == self::VALID_STATUS[2]) {
710  $status = UploadStatus::CLOSED;
711  } elseif ($newStatus == self::VALID_STATUS[3]) {
712  $status = UploadStatus::REJECTED;
713  } else {
714  $status = UploadStatus::OPEN;
715  }
716  $uploadBrowseProxy->setStatusAndComment($id, $status, $comment);
717  }
718  // Handle update of name
719  if (
720  $isJsonRequest &&
721  array_key_exists(self::FILTER_NAME, $bodyContent) &&
722  strlen(trim($bodyContent[self::FILTER_NAME])) > 0
723  ) {
724  $newName = trim($bodyContent[self::FILTER_NAME]);
725  }
726  // Handle update of description
727  if (
728  $isJsonRequest &&
729  array_key_exists("uploadDescription", $bodyContent) &&
730  strlen(trim($bodyContent["uploadDescription"])) > 0
731  ) {
732  $newDescription = trim($bodyContent["uploadDescription"]);
733  }
734  if ($newName != null || $newDescription != null) {
736  $uploadProperties = $this->restHelper->getPlugin('upload_properties');
737  $updated = $uploadProperties->UpdateUploadProperties($id, $newName, $newDescription);
738  if ($updated == 2) {
739  throw new HttpBadRequestException("Invalid request to update upload name and description.");
740  }
741  }
742 
743  $returnVal = new Info(202, "Upload updated successfully.", InfoType::INFO);
744  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
745  }
746 
752  private function isAdj2nestDone($id): void
753  {
754  $itemTreeBounds = $this->restHelper->getUploadDao()->getParentItemBounds(
755  $id);
756  if ($itemTreeBounds === false || empty($itemTreeBounds->getLeft())) {
758  "Ununpack job not started. Please check job status at " .
759  "/api/v1/jobs?upload=" . $id))
760  ->setHeaders(['Retry-After' => '60',
761  'Look-at' => "/api/v1/jobs?upload=" . $id]);
762  }
763  }
764 
774  private function areAgentsScheduled($uploadId, $agents, $response): void
775  {
776  global $container;
777  $agentDao = $container->get('dao.agent');
778 
779  $agentList = array_keys(AgentRef::AGENT_LIST);
780  $intersectArray = array_intersect($agents, $agentList);
781 
782  if (count($agents) != count($intersectArray)) {
783  throw new HttpBadRequestException("Agent should be any of " .
784  implode(", ", $agentList) . ". " . implode(",", $agents) . " passed.");
785  } else {
786  // Agent is valid, check if they have ars tables.
787  foreach ($agents as $agent) {
788  if (! $agentDao->arsTableExists($agent)) {
790  "Agent $agent not scheduled for the upload. " .
791  "Please POST to /jobs");
792  }
793  }
794  }
795 
796  $scanProxy = new ScanJobProxy($agentDao, $uploadId);
797  $agentList = $scanProxy->createAgentStatus($agents);
798 
799  foreach ($agentList as $agent) {
800  if (! array_key_exists('currentAgentId', $agent)) {
802  "Agent " . $agent["agentName"] .
803  " not scheduled for the upload. Please POST to /jobs");
804  }
805  if (array_key_exists('isAgentRunning', $agent) &&
806  $agent['isAgentRunning']) {
808  "Agent " . $agent["agentName"] . " is running. " .
809  "Please check job status at /api/v1/jobs?upload=" . $uploadId))
810  ->setHeaders(['Retry-After' => '60',
811  'Look-at' => "/api/v1/jobs?upload=" . $uploadId]);
812  }
813  }
814  }
815 
825  public function setUploadPermissions($request, $response, $args)
826  {
827  $returnVal = null;
828  // checking if the scheduler is running or not
829  $commu_status = fo_communicate_with_scheduler('status', $response_from_scheduler, $error_info);
830  if (!$commu_status) {
831  throw new HttpServiceUnavailableException("Scheduler is not running!");
832  }
833  // Initialising upload-permissions plugin
834  global $container;
835  $restHelper = $container->get('helper.restHelper');
836  $uploadPermissionObj = $restHelper->getPlugin('upload_permissions');
837 
838  $dbManager = $this->dbHelper->getDbManager();
839  // parsing the request body
840  $reqBody = $this->getParsedBody($request);
841 
842  $folder_pk = intval($reqBody['folderId']);
843  $upload_pk = intval($args['id']);
844  $this->uploadAccessible($upload_pk);
845  $allUploadsPerm = $reqBody['allUploadsPermission'] ? 1 : 0;
846  $newgroup = intval($reqBody['groupId']);
847  $newperm = $this->getEquivalentValueForPermission($reqBody['newPermission']);
848  $public_perm = isset($reqBody['publicPermission']) ? $this->getEquivalentValueForPermission($reqBody['publicPermission']) : -1;
849 
850  $query = "SELECT perm, perm_upload_pk FROM perm_upload WHERE upload_fk=$1 and group_fk=$2;";
851  $result = $dbManager->getSingleRow($query, [$upload_pk, $newgroup], __METHOD__.".getOldPerm");
852  $perm_upload_pk = 0;
853  $perm = 0;
854  if (!empty($result)) {
855  $perm_upload_pk = intVal($result['perm_upload_pk']);
856  $perm = $newperm;
857  }
858 
859  $uploadPermissionObj->editPermissionsForUpload($commu_status, $folder_pk, $upload_pk, $allUploadsPerm, $perm_upload_pk, $perm, $newgroup, $newperm, $public_perm);
860 
861  $returnVal = new Info(202, "Permissions updated successfully!", InfoType::INFO);
862  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
863  }
864 
865  public function getEquivalentValueForPermission($perm)
866  {
867  switch ($perm) {
868  case 'read_only':
869  return Auth::PERM_READ;
870  case 'read_write':
871  return Auth::PERM_WRITE;
872  case 'clearing_admin':
873  return Auth::PERM_CADMIN;
874  case 'admin':
875  return Auth::PERM_ADMIN;
876  default:
877  return Auth::PERM_NONE;
878  }
879  }
880 
890  public function getGroupsWithPermissions($request, $response, $args)
891  {
892  $apiVersion = ApiVersion::getVersion($request);
893  $upload_pk = intval($args['id']);
894  $this->uploadAccessible($upload_pk);
895  $publicPerm = $this->restHelper->getUploadPermissionDao()->getPublicPermission($upload_pk);
896  $permGroups = $this->restHelper->getUploadPermissionDao()->getPermissionGroups($upload_pk);
897 
898  // Removing the perm_upload_pk parameter in response
899  $finalPermGroups = [];
900  foreach ($permGroups as $value) {
901  $groupPerm = new GroupPermission($value['perm'], $value['group_pk'], $value['group_name']);
902  $finalPermGroups[] = $groupPerm->getArray($apiVersion);
903  }
904  $res = new Permissions($publicPerm, $finalPermGroups);
905  return $response->withJson($res->getArray($apiVersion), 200);
906  }
907 
917  public function getMainLicenses($request, $response, $args)
918  {
919  $uploadId = intval($args['id']);
920  $this->uploadAccessible($uploadId);
921 
923  $clearingDao = $this->container->get('dao.clearing');
924  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
925  $licenseDao = $this->container->get('dao.license');
926  $licenses = array();
927 
928  foreach ($licenseIds as $value) {
929  $licenseId = intval($value);
930  $obligations = $licenseDao->getLicenseObligations([$licenseId],
931  false);
932  $obligations = array_merge($obligations,
933  $licenseDao->getLicenseObligations([$licenseId], true));
934  $obligationList = [];
935  foreach ($obligations as $obligation) {
936  $obligationList[] = new Obligation(
937  $obligation['ob_pk'],
938  $obligation['ob_topic'],
939  $obligation['ob_type'],
940  $obligation['ob_text'],
941  $obligation['ob_classification'],
942  $obligation['ob_comment']
943  );
944  }
945  $license = $licenseDao->getLicenseById($licenseId);
946  $licenseObj = new License(
947  $license->getId(),
948  $license->getShortName(),
949  $license->getFullName(),
950  $license->getText(),
951  $license->getUrl(),
952  $obligationList,
953  $license->getRisk()
954  );
955  $licenses[] = $licenseObj->getArray();
956  }
957  return $response->withJson($licenses, 200);
958  }
959 
969  public function setMainLicense($request, $response, $args)
970  {
971  $uploadId = intval($args['id']);
972  $body = $this->getParsedBody($request);
973  $shortName = $body['shortName'];
974  $licenseDao = $this->container->get('dao.license');
975  $clearingDao = $this->container->get('dao.clearing');
976 
977  $this->uploadAccessible($uploadId);
978 
979  if (empty($shortName)) {
980  throw new HttpBadRequestException("Short name missing from request.");
981  }
982  $license = $licenseDao->getLicenseByShortName($shortName,
983  $this->restHelper->getGroupId());
984 
985  if ($license === null) {
986  throw new HttpNotFoundException(
987  "No license with shortname '$shortName' found.");
988  }
989 
990  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
991  if (in_array($license->getId(), $licenseIds)) {
992  throw new HttpBadRequestException(
993  "License already exists for this upload.");
994  }
995 
997  $clearingDao = $this->container->get('dao.clearing');
998  $clearingDao->makeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
999  $returnVal = new Info(200, "Successfully added new main license", InfoType::INFO);
1000  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1001  }
1002 
1003  /***
1004  * Remove the main license from the upload
1005  *
1006  * @param ServerRequestInterface $request
1007  * @param ResponseHelper $response
1008  * @param array $args
1009  * @return ResponseHelper
1010  * @throws HttpErrorException
1011  */
1012  public function removeMainLicense($request, $response, $args)
1013  {
1014  $uploadId = intval($args['id']);
1015  $shortName = $args['shortName'];
1016  $licenseDao = $this->container->get('dao.license');
1017  $clearingDao = $this->container->get('dao.clearing');
1018  $license = $licenseDao->getLicenseByShortName($shortName, $this->restHelper->getGroupId());
1019 
1020  $this->uploadAccessible($uploadId);
1021 
1022  if ($license === null) {
1023  throw new HttpNotFoundException(
1024  "No license with shortname '$shortName' found.");
1025  }
1026  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1027  if (!in_array($license->getId(), $licenseIds)) {
1028  throw new HttpBadRequestException(
1029  "License '$shortName' is not a main license for this upload.");
1030  }
1031 
1032  $clearingDao = $this->container->get('dao.clearing');
1033  $clearingDao->removeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1034  $returnVal = new Info(200, "Main license removed successfully.", InfoType::INFO);
1035 
1036  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1037  }
1038 
1048  public function getClearingProgressInfo($request, $response, $args)
1049  {
1050  $uploadId = intval($args['id']);
1051  $uploadDao = $this->restHelper->getUploadDao();
1052 
1053  $this->uploadAccessible($uploadId);
1054 
1055  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1056 
1057  $noLicenseUploadTreeView = new UploadTreeProxy($uploadId,
1058  array(UploadTreeProxy::OPT_SKIP_THESE => "noLicense",
1059  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1060  $uploadTreeTableName,
1061  'no_license_uploadtree' . $uploadId);
1062 
1063  $filesOfInterest = $noLicenseUploadTreeView->count();
1064 
1065  $nonClearedUploadTreeView = new UploadTreeProxy($uploadId,
1066  array(UploadTreeProxy::OPT_SKIP_THESE => "alreadyCleared",
1067  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1068  $uploadTreeTableName,
1069  'already_cleared_uploadtree' . $uploadId);
1070  $filesToBeCleared = $nonClearedUploadTreeView->count();
1071 
1072  $filesAlreadyCleared = $filesOfInterest - $filesToBeCleared;
1073 
1074  $res = [
1075  "totalFilesOfInterest" => intval($filesOfInterest),
1076  "totalFilesCleared" => intval($filesAlreadyCleared),
1077  ];
1078  return $response->withJson($res, 200);
1079  }
1080 
1090  public function getLicensesHistogram($request, $response, $args)
1091  {
1092  $agentDao = $this->container->get('dao.agent');
1093  $clearingDao = $this->container->get('dao.clearing');
1094  $licenseDao = $this->container->get('dao.license');
1095 
1096  $uploadId = intval($args['id']);
1097  $uploadDao = $this->restHelper->getUploadDao();
1098  $query = $request->getQueryParams();
1099  $selectedAgentId = $query['agentId'] ?? null;
1100 
1101  $this->uploadAccessible($uploadId);
1102 
1103  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1104  throw new HttpNotFoundException("Agent does not exist.");
1105  }
1106 
1107  $scannerAgents = array_keys($this->agentNames);
1108  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1109  $scanJobProxy->createAgentStatus($scannerAgents);
1110  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1111  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1112  $editedLicenses = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1113  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1114  $scannedLicenses = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1115  $allScannerLicenseNames = array_keys($scannedLicenses);
1116  $allEditedLicenseNames = array_keys($editedLicenses);
1117  $allLicNames = array_unique(array_merge($allScannerLicenseNames, $allEditedLicenseNames));
1118  $realLicNames = array_diff($allLicNames, array(LicenseDao::NO_LICENSE_FOUND));
1119  $totalScannerLicenseCount = 0;
1120  $editedTotalLicenseCount = 0;
1121 
1122  $res = array();
1123  foreach ($realLicNames as $licenseShortName) {
1124  $count = 0;
1125  if (array_key_exists($licenseShortName, $scannedLicenses)) {
1126  $count = $scannedLicenses[$licenseShortName]['unique'];
1127  $rfId = $scannedLicenses[$licenseShortName]['rf_pk'];
1128  } else {
1129  $rfId = $editedLicenses[$licenseShortName]['rf_pk'];
1130  }
1131  $editedCount = array_key_exists($licenseShortName, $editedLicenses) ? $editedLicenses[$licenseShortName]['count'] : 0;
1132  $totalScannerLicenseCount += $count;
1133  $editedTotalLicenseCount += $editedCount;
1134  $scannerCountLink = $count;
1135  $editedLink = $editedCount;
1136 
1137  $res[] = array($scannerCountLink, $editedLink, array($licenseShortName, $rfId));
1138  }
1139 
1140  $outputArray = [];
1141 
1142  foreach ($res as $item) {
1143  $outputArray[] = [
1144  "id" => intval($item[2][1]),
1145  "name" => $item[2][0],
1146  "scannerCount" => intval($item[0]),
1147  "concludedCount" => intval($item[1]),
1148  ];
1149  }
1150  return $response->withJson($outputArray, 200);
1151  }
1152 
1162  public function getAllAgents($request, $response, $args)
1163  {
1164  $uploadId = intval($args['id']);
1165 
1166  $this->uploadAccessible($uploadId);
1167 
1168  $scannerAgents = array_keys($this->agentNames);
1169  $agentDao = $this->container->get('dao.agent');
1170  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1171  $res = $scanJobProxy->createAgentStatus($scannerAgents);
1172 
1173  $outputArray = [];
1174  foreach ($res as &$item) {
1175  $successfulAgents = [];
1176  if (count($item['successfulAgents']) > 0) {
1177  $item['isAgentRunning'] = false;
1178  } else {
1179  $item['currentAgentId'] = $agentDao->getCurrentAgentRef($item["agentName"])->getAgentId();
1180  $item['currentAgentRev'] = "";
1181  }
1182  foreach ($item['successfulAgents'] as &$agent) {
1183  $successfulAgent = new SuccessfulAgent(intval($agent['agent_id']), $agent['agent_rev'], $agent['agent_name']);
1184  $successfulAgents[] = $successfulAgent->getArray(ApiVersion::getVersion($request));
1185  }
1186  $agent = new Agent($successfulAgents, $item['uploadId'], $item['agentName'], $item['currentAgentId'], $item['currentAgentRev'], $item['isAgentRunning']);
1187  $outputArray[] = $agent->getArray(ApiVersion::getVersion($request));
1188  }
1189  return $response->withJson($outputArray, 200);
1190  }
1191 
1201  public function getEditedLicenses($request, $response, $args)
1202  {
1203  $uploadId = intval($args['id']);
1204 
1205  $this->uploadAccessible($uploadId);
1206 
1207  $clearingDao = $this->container->get('dao.clearing');
1208  $uploadDao = $this->restHelper->getUploadDao();
1209  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1210  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1211  $res = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1212  $outputArray = [];
1213 
1214  foreach ($res as $key => $value) {
1215  $editedLicense = new EditedLicense(intval($value["rf_pk"]), $key, intval($value["count"]), $value["spdx_id"]);
1216  $outputArray[] = $editedLicense->getArray(ApiVersion::getVersion($request));
1217  }
1218  return $response->withJson($outputArray, 200);
1219  }
1220 
1230  public function getReuseReportSummary($request, $response, $args)
1231  {
1232  $uploadId = intval($args['id']);
1233  $this->uploadAccessible($uploadId);
1234 
1236  $reuseReportProcess = $this->container->get('businessrules.reusereportprocessor');
1237  $res = $reuseReportProcess->getReuseSummary($uploadId);
1238  return $response->withJson($res, 200);
1239  }
1240 
1250  public function getScannedLicenses($request, $response, $args)
1251  {
1252  $uploadId = intval($args['id']);
1253  $query = $request->getQueryParams();
1254  $selectedAgentId = $query['agentId'] ?? null;
1255  $licenseDao = $this->container->get('dao.license');
1256 
1257  $this->uploadAccessible($uploadId);
1258  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1259  throw new HttpNotFoundException("Agent does not exist.");
1260  }
1261  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
1262  $scanJobProxy = new ScanJobProxy($this->agentDao, $uploadId);
1263  $scanJobProxy->createAgentStatus($scannerAgents);
1264  $uploadDao = $this->restHelper->getUploadDao();
1265  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1266  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1267  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1268  $res = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1269  $outputArray = [];
1270 
1271  foreach ($res as $key => $value) {
1272  $scannedLicense = new ScannedLicense($licenseDao->getLicenseByShortName($key)->getId(), $key, $value['count'], $value['unique'], $value['spdx_id']);
1273  $outputArray[] = $scannedLicense->getArray(ApiVersion::getVersion($request));
1274  }
1275  return $response->withJson($outputArray, 200);
1276  }
1286  public function getAgentsRevision($request, $response, $args)
1287  {
1288  $agentDao = $this->container->get('dao.agent');
1289  $uploadId = intval($args['id']);
1290 
1291  $this->uploadAccessible($uploadId);
1292 
1293  $scannerAgents = array_keys($this->agentNames);
1294  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1295  $scanJobProxy->createAgentStatus($scannerAgents);
1296 
1297  $res = array();
1298  foreach ($scanJobProxy->getSuccessfulAgents() as $agent) {
1299  $res[] = array(
1300  "id" => $agent->getAgentId(),
1301  "name" => $agent->getAgentName(),
1302  "revision" => $agent->getAgentRevision(),
1303  );
1304  }
1305  return $response->withJson($res, 200);
1306  }
1307 
1317  public function getTopItem($request, $response, $args)
1318  {
1319  $uploadId = intval($args['id']);
1320  if (!$this->dbHelper->doesIdExist("upload", "upload_pk", $uploadId)) {
1321  $returnVal = new Info(404, "Upload does not exist", InfoType::ERROR);
1322  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1323  }
1324  $uploadDao = $this->restHelper->getUploadDao();
1325  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId,
1326  $uploadDao->getUploadtreeTableName($uploadId));
1327  if ($itemTreeBounds === false) {
1328  $error = new Info(500, "Unable to get top item.", InfoType::ERROR);
1329  return $response->withJson($error->getArray(), $error->getCode());
1330  }
1331  $info = new Info(200, $itemTreeBounds->getItemId(), InfoType::INFO);
1332  return $response->withJson($info->getArray(), $info->getCode());
1333  }
1334 }
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