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  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  } else {
471  $scanOptions = $reqBody['scanOptions'];
472  }
473  }
474 
475  if (! is_array($scanOptions)) {
476  $scanOptions = [];
477  }
478 
479  $uploadHelper = new UploadHelper();
480 
481  if ($uploadType != "file" && (empty($reqBody) ||
482  ! array_key_exists("location", $reqBody))) {
483  throw new HttpBadRequestException(
484  "Require location object if uploadType != file");
485  }
486  if (empty($folderId) ||
487  !is_numeric($folderId) && $folderId > 0) {
488  throw new HttpBadRequestException("folderId must be a positive integer!");
489  }
490 
491  $allFolderIds = $this->restHelper->getFolderDao()->getAllFolderIds();
492  if (!in_array($folderId, $allFolderIds)) {
493  throw new HttpNotFoundException("folderId $folderId does not exists!");
494  }
495  if (!$this->restHelper->getFolderDao()->isFolderAccessible($folderId)) {
496  throw new HttpForbiddenException("folderId $folderId is not accessible!");
497  }
498 
499  $locationObject = [];
500  if (array_key_exists("location", $reqBody)) {
501  $locationObject = $reqBody["location"];
502  } elseif ($uploadType != 'file') {
503  throw new HttpBadRequestException(
504  "Require location object if uploadType != file");
505  }
506 
507  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
508  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
509  $folderId, $description, $public, $ignoreScm, $uploadType,
510  $applyGlobal, $excludefolder);
511  } else {
512  $uploadResponse = $uploadHelper->createNewUpload($locationObject,
513  $folderId, $description, $public, $ignoreScm, $uploadType,
514  $applyGlobal);
515  }
516  $status = $uploadResponse[0];
517  $message = $uploadResponse[1];
518  $statusDescription = $uploadResponse[2];
519  if (! $status) {
520  throw new HttpInternalServerErrorException($message . "\n" .
521  $statusDescription);
522  }
523 
524  $uploadId = $uploadResponse[3];
525  if (! empty($scanOptions)) {
526  $info = $uploadHelper->handleScheduleAnalysis(intval($uploadId),
527  intval($folderId), $scanOptions, true);
528  if ($info->getCode() == 201) {
529  $info = new Info($info->getCode(), intval($uploadId), $info->getType());
530  }
531  } else {
532  $info = new Info(201, intval($uploadId), InfoType::INFO);
533  }
534  if (array_key_exists("mainLicense", $reqBody) &&
535  ! empty($reqBody["mainLicense"])) {
536  global $container;
538  $licenseDao = $container->get('dao.license');
539  $mainLicense = $licenseDao
540  ->getLicenseByShortName($reqBody["mainLicense"]);
541  if ($mainLicense !== null) {
543  $clearingDao = $container->get('dao.clearing');
544  $clearingDao->makeMainLicense($uploadId,
545  $this->restHelper->getGroupId(), $mainLicense->getId());
546  }
547  }
548  return $response->withJson($info->getArray(), $info->getCode());
549  }
550 
560  public function getUploadLicenses($request, $response, $args)
561  {
562  $id = intval($args['id']);
563  $query = $request->getQueryParams();
564  $apiVersion = ApiVersion::getVersion($request);
565  if ($apiVersion == ApiVersion::V2) {
566  $page = $query['page'] ?? "";
567  $limit = $query['limit'] ?? "";
568  } else {
569  $page = $request->getHeaderLine("page");
570  $limit = $request->getHeaderLine("limit");
571  }
572  if (! array_key_exists(self::AGENT_PARAM, $query)) {
573  throw new HttpBadRequestException("agent parameter missing from query.");
574  }
575  $agents = explode(",", $query[self::AGENT_PARAM]);
576  $containers = true;
577  if (array_key_exists(self::CONTAINER_PARAM, $query)) {
578  $containers = (strcasecmp($query[self::CONTAINER_PARAM], "true") === 0);
579  }
580 
581  $license = true;
582  if (array_key_exists('license', $query)) {
583  $license = (strcasecmp($query['license'], "true") === 0);
584  }
585 
586  $copyright = false;
587  if (array_key_exists('copyright', $query)) {
588  $copyright = (strcasecmp($query['copyright'], "true") === 0);
589  }
590 
591  if (!$license && !$copyright) {
592  throw new HttpBadRequestException(
593  "'license' and 'copyright' atleast one should be true.");
594  }
595 
596  $this->uploadAccessible($id);
597  $this->isAdj2nestDone($id);
598 
599  $this->areAgentsScheduled($id, $agents, $response);
600 
601  /*
602  * check if page && limit are numeric, if existing
603  */
604  if ((! ($page==='') && (! is_numeric($page) || $page < 1)) ||
605  (! ($limit==='') && (! is_numeric($limit) || $limit < 1))) {
606  throw new HttpBadRequestException(
607  "page and limit need to be positive integers!");
608  }
609 
610  // set page to 1 by default
611  if (empty($page)) {
612  $page = 1;
613  }
614 
615  // set limit to 50 by default and max as 1000
616  if (empty($limit)) {
617  $limit = 50;
618  } else if ($limit > 1000) {
619  $limit = 1000;
620  }
621 
622  $uploadHelper = new UploadHelper();
623  list($licenseList, $count) = $uploadHelper->getUploadLicenseList($id, $agents, $containers, $license, $copyright, $page-1, $limit, $apiVersion);
624  $totalPages = intval(ceil($count / $limit));
625  return $response->withHeader("X-Total-Pages", $totalPages)->withJson($licenseList, 200);
626  }
627 
637  public function getUploadCopyrights($request, $response, $args)
638  {
639  $id = intval($args['id']);
640  $this->uploadAccessible($id);
641  $this->isAdj2nestDone($id);
642  $uploadHelper = new UploadHelper();
643  $licenseList = $uploadHelper->getUploadCopyrightList($id);
644  return $response->withJson($licenseList, 200);
645  }
646 
656  public function updateUpload($request, $response, $args)
657  {
658  $id = intval($args['id']);
659  $query = $request->getQueryParams();
660  $userDao = $this->restHelper->getUserDao();
661  $userId = $this->restHelper->getUserId();
662  $groupId = $this->restHelper->getGroupId();
663  $isJsonRequest = $this->isJsonRequest($request);
664 
665  $perm = $userDao->isAdvisorOrAdmin($userId, $groupId);
666  if (!$perm) {
667  throw new HttpForbiddenException("Not advisor or admin of current group. " .
668  "Can not update upload.");
669  }
670  $uploadBrowseProxy = new UploadBrowseProxy(
671  $groupId,
672  $perm,
673  $this->dbHelper->getDbManager()
674  );
675 
676  $assignee = null;
677  $status = null;
678  $comment = null;
679  $newName = null;
680  $newDescription = null;
681 
682  if ($isJsonRequest) {
683  $bodyContent = $this->getParsedBody($request);
684  } else {
685  $body = $request->getBody();
686  $bodyContent = $body->getContents();
687  $body->close();
688  }
689 
690  // Handle assignee info
691  if (array_key_exists(self::FILTER_ASSIGNEE, $query)) {
692  $assignee = filter_var($query[self::FILTER_ASSIGNEE], FILTER_VALIDATE_INT);
693  $userList = $userDao->getUserChoices($groupId);
694  if (!array_key_exists($assignee, $userList)) {
695  throw new HttpNotFoundException(
696  "New assignee does not have permission on upload.");
697  }
698  $uploadBrowseProxy->updateTable("assignee", $id, $assignee);
699  }
700  // Handle new status
701  if (
702  array_key_exists(self::FILTER_STATUS, $query) &&
703  in_array(strtolower($query[self::FILTER_STATUS]), self::VALID_STATUS)
704  ) {
705  $newStatus = strtolower($query[self::FILTER_STATUS]);
706  $comment = '';
707  if (in_array($newStatus, ["closed", "rejected"])) {
708  if ($isJsonRequest && array_key_exists("comment", $bodyContent)) {
709  $comment = $bodyContent["comment"];
710  } else {
711  $comment = $bodyContent;
712  }
713  }
714  $status = 0;
715  if ($newStatus == self::VALID_STATUS[1]) {
716  $status = UploadStatus::IN_PROGRESS;
717  } elseif ($newStatus == self::VALID_STATUS[2]) {
718  $status = UploadStatus::CLOSED;
719  } elseif ($newStatus == self::VALID_STATUS[3]) {
720  $status = UploadStatus::REJECTED;
721  } else {
722  $status = UploadStatus::OPEN;
723  }
724  $uploadBrowseProxy->setStatusAndComment($id, $status, $comment);
725  }
726  // Handle update of name
727  if (
728  $isJsonRequest &&
729  array_key_exists(self::FILTER_NAME, $bodyContent) &&
730  strlen(trim($bodyContent[self::FILTER_NAME])) > 0
731  ) {
732  $newName = trim($bodyContent[self::FILTER_NAME]);
733  }
734  // Handle update of description
735  if (
736  $isJsonRequest &&
737  array_key_exists("uploadDescription", $bodyContent) &&
738  strlen(trim($bodyContent["uploadDescription"])) > 0
739  ) {
740  $newDescription = trim($bodyContent["uploadDescription"]);
741  }
742  if ($newName != null || $newDescription != null) {
744  $uploadProperties = $this->restHelper->getPlugin('upload_properties');
745  $updated = $uploadProperties->UpdateUploadProperties($id, $newName, $newDescription);
746  if ($updated == 2) {
747  throw new HttpBadRequestException("Invalid request to update upload name and description.");
748  }
749  }
750 
751  $returnVal = new Info(202, "Upload updated successfully.", InfoType::INFO);
752  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
753  }
754 
760  private function isAdj2nestDone($id): void
761  {
762  $itemTreeBounds = $this->restHelper->getUploadDao()->getParentItemBounds(
763  $id);
764  if ($itemTreeBounds === false || empty($itemTreeBounds->getLeft())) {
766  "Ununpack job not started. Please check job status at " .
767  "/api/v1/jobs?upload=" . $id))
768  ->setHeaders(['Retry-After' => '60',
769  'Look-at' => "/api/v1/jobs?upload=" . $id]);
770  }
771  }
772 
782  private function areAgentsScheduled($uploadId, $agents, $response): void
783  {
784  global $container;
785  $agentDao = $container->get('dao.agent');
786 
787  $agentList = array_keys(AgentRef::AGENT_LIST);
788  $intersectArray = array_intersect($agents, $agentList);
789 
790  if (count($agents) != count($intersectArray)) {
791  throw new HttpBadRequestException("Agent should be any of " .
792  implode(", ", $agentList) . ". " . implode(",", $agents) . " passed.");
793  } else {
794  // Agent is valid, check if they have ars tables.
795  foreach ($agents as $agent) {
796  if (! $agentDao->arsTableExists($agent)) {
798  "Agent $agent not scheduled for the upload. " .
799  "Please POST to /jobs");
800  }
801  }
802  }
803 
804  $scanProxy = new ScanJobProxy($agentDao, $uploadId);
805  $agentList = $scanProxy->createAgentStatus($agents);
806 
807  foreach ($agentList as $agent) {
808  if (! array_key_exists('currentAgentId', $agent)) {
810  "Agent " . $agent["agentName"] .
811  " not scheduled for the upload. Please POST to /jobs");
812  }
813  if (array_key_exists('isAgentRunning', $agent) &&
814  $agent['isAgentRunning']) {
816  "Agent " . $agent["agentName"] . " is running. " .
817  "Please check job status at /api/v1/jobs?upload=" . $uploadId))
818  ->setHeaders(['Retry-After' => '60',
819  'Look-at' => "/api/v1/jobs?upload=" . $uploadId]);
820  }
821  }
822  }
823 
833  public function setUploadPermissions($request, $response, $args)
834  {
835  $returnVal = null;
836  // checking if the scheduler is running or not
837  $commu_status = fo_communicate_with_scheduler('status', $response_from_scheduler, $error_info);
838  if (!$commu_status) {
839  throw new HttpServiceUnavailableException("Scheduler is not running!");
840  }
841  // Initialising upload-permissions plugin
842  global $container;
843  $restHelper = $container->get('helper.restHelper');
844  $uploadPermissionObj = $restHelper->getPlugin('upload_permissions');
845 
846  $dbManager = $this->dbHelper->getDbManager();
847  // parsing the request body
848  $reqBody = $this->getParsedBody($request);
849 
850  $folder_pk = intval($reqBody['folderId']);
851  $upload_pk = intval($args['id']);
852  $this->uploadAccessible($upload_pk);
853  $allUploadsPerm = $reqBody['allUploadsPermission'] ? 1 : 0;
854  $newgroup = intval($reqBody['groupId']);
855  $newperm = $this->getEquivalentValueForPermission($reqBody['newPermission']);
856  $public_perm = isset($reqBody['publicPermission']) ? $this->getEquivalentValueForPermission($reqBody['publicPermission']) : -1;
857 
858  $query = "SELECT perm, perm_upload_pk FROM perm_upload WHERE upload_fk=$1 and group_fk=$2;";
859  $result = $dbManager->getSingleRow($query, [$upload_pk, $newgroup], __METHOD__.".getOldPerm");
860  $perm_upload_pk = 0;
861  $perm = 0;
862  if (!empty($result)) {
863  $perm_upload_pk = intVal($result['perm_upload_pk']);
864  $perm = $newperm;
865  }
866 
867  $uploadPermissionObj->editPermissionsForUpload($commu_status, $folder_pk, $upload_pk, $allUploadsPerm, $perm_upload_pk, $perm, $newgroup, $newperm, $public_perm);
868 
869  $returnVal = new Info(202, "Permissions updated successfully!", InfoType::INFO);
870  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
871  }
872 
873  public function getEquivalentValueForPermission($perm)
874  {
875  switch ($perm) {
876  case 'read_only':
877  return Auth::PERM_READ;
878  case 'read_write':
879  return Auth::PERM_WRITE;
880  case 'clearing_admin':
881  return Auth::PERM_CADMIN;
882  case 'admin':
883  return Auth::PERM_ADMIN;
884  default:
885  return Auth::PERM_NONE;
886  }
887  }
888 
898  public function getGroupsWithPermissions($request, $response, $args)
899  {
900  $apiVersion = ApiVersion::getVersion($request);
901  $upload_pk = intval($args['id']);
902  $this->uploadAccessible($upload_pk);
903  $publicPerm = $this->restHelper->getUploadPermissionDao()->getPublicPermission($upload_pk);
904  $permGroups = $this->restHelper->getUploadPermissionDao()->getPermissionGroups($upload_pk);
905 
906  // Removing the perm_upload_pk parameter in response
907  $finalPermGroups = [];
908  foreach ($permGroups as $value) {
909  $groupPerm = new GroupPermission($value['perm'], $value['group_pk'], $value['group_name']);
910  $finalPermGroups[] = $groupPerm->getArray($apiVersion);
911  }
912  $res = new Permissions($publicPerm, $finalPermGroups);
913  return $response->withJson($res->getArray($apiVersion), 200);
914  }
915 
925  public function getMainLicenses($request, $response, $args)
926  {
927  $uploadId = intval($args['id']);
928  $this->uploadAccessible($uploadId);
929 
931  $clearingDao = $this->container->get('dao.clearing');
932  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
933  $licenseDao = $this->container->get('dao.license');
934  $licenses = array();
935 
936  foreach ($licenseIds as $value) {
937  $licenseId = intval($value);
938  $obligations = $licenseDao->getLicenseObligations([$licenseId],
939  false);
940  $obligations = array_merge($obligations,
941  $licenseDao->getLicenseObligations([$licenseId], true));
942  $obligationList = [];
943  foreach ($obligations as $obligation) {
944  $obligationList[] = new Obligation(
945  $obligation['ob_pk'],
946  $obligation['ob_topic'],
947  $obligation['ob_type'],
948  $obligation['ob_text'],
949  $obligation['ob_classification'],
950  $obligation['ob_comment']
951  );
952  }
953  $license = $licenseDao->getLicenseById($licenseId);
954  $licenseObj = new License(
955  $license->getId(),
956  $license->getShortName(),
957  $license->getFullName(),
958  $license->getText(),
959  $license->getUrl(),
960  $obligationList,
961  $license->getRisk()
962  );
963  $licenses[] = $licenseObj->getArray();
964  }
965  return $response->withJson($licenses, 200);
966  }
967 
977  public function setMainLicense($request, $response, $args)
978  {
979  $uploadId = intval($args['id']);
980  $body = $this->getParsedBody($request);
981  $shortName = $body['shortName'];
982  $licenseDao = $this->container->get('dao.license');
983  $clearingDao = $this->container->get('dao.clearing');
984 
985  $this->uploadAccessible($uploadId);
986 
987  if (empty($shortName)) {
988  throw new HttpBadRequestException("Short name missing from request.");
989  }
990  $license = $licenseDao->getLicenseByShortName($shortName,
991  $this->restHelper->getGroupId());
992 
993  if ($license === null) {
994  throw new HttpNotFoundException(
995  "No license with shortname '$shortName' found.");
996  }
997 
998  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
999  if (in_array($license->getId(), $licenseIds)) {
1000  throw new HttpBadRequestException(
1001  "License already exists for this upload.");
1002  }
1003 
1005  $clearingDao = $this->container->get('dao.clearing');
1006  $clearingDao->makeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1007  $returnVal = new Info(200, "Successfully added new main license", InfoType::INFO);
1008  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1009  }
1010 
1011  /***
1012  * Remove the main license from the upload
1013  *
1014  * @param ServerRequestInterface $request
1015  * @param ResponseHelper $response
1016  * @param array $args
1017  * @return ResponseHelper
1018  * @throws HttpErrorException
1019  */
1020  public function removeMainLicense($request, $response, $args)
1021  {
1022  $uploadId = intval($args['id']);
1023  $shortName = $args['shortName'];
1024  $licenseDao = $this->container->get('dao.license');
1025  $clearingDao = $this->container->get('dao.clearing');
1026  $license = $licenseDao->getLicenseByShortName($shortName, $this->restHelper->getGroupId());
1027 
1028  $this->uploadAccessible($uploadId);
1029 
1030  if ($license === null) {
1031  throw new HttpNotFoundException(
1032  "No license with shortname '$shortName' found.");
1033  }
1034  $licenseIds = $clearingDao->getMainLicenseIds($uploadId, $this->restHelper->getGroupId());
1035  if (!in_array($license->getId(), $licenseIds)) {
1036  throw new HttpBadRequestException(
1037  "License '$shortName' is not a main license for this upload.");
1038  }
1039 
1040  $clearingDao = $this->container->get('dao.clearing');
1041  $clearingDao->removeMainLicense($uploadId, $this->restHelper->getGroupId(), $license->getId());
1042  $returnVal = new Info(200, "Main license removed successfully.", InfoType::INFO);
1043 
1044  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1045  }
1046 
1056  public function getClearingProgressInfo($request, $response, $args)
1057  {
1058  $uploadId = intval($args['id']);
1059  $uploadDao = $this->restHelper->getUploadDao();
1060 
1061  $this->uploadAccessible($uploadId);
1062 
1063  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1064 
1065  $noLicenseUploadTreeView = new UploadTreeProxy($uploadId,
1066  array(UploadTreeProxy::OPT_SKIP_THESE => "noLicense",
1067  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1068  $uploadTreeTableName,
1069  'no_license_uploadtree' . $uploadId);
1070 
1071  $filesOfInterest = $noLicenseUploadTreeView->count();
1072 
1073  $nonClearedUploadTreeView = new UploadTreeProxy($uploadId,
1074  array(UploadTreeProxy::OPT_SKIP_THESE => "alreadyCleared",
1075  UploadTreeProxy::OPT_GROUP_ID => $this->restHelper->getGroupId()),
1076  $uploadTreeTableName,
1077  'already_cleared_uploadtree' . $uploadId);
1078  $filesToBeCleared = $nonClearedUploadTreeView->count();
1079 
1080  $filesAlreadyCleared = $filesOfInterest - $filesToBeCleared;
1081 
1082  $res = [
1083  "totalFilesOfInterest" => intval($filesOfInterest),
1084  "totalFilesCleared" => intval($filesAlreadyCleared),
1085  ];
1086  return $response->withJson($res, 200);
1087  }
1088 
1098  public function getLicensesHistogram($request, $response, $args)
1099  {
1100  $agentDao = $this->container->get('dao.agent');
1101  $clearingDao = $this->container->get('dao.clearing');
1102  $licenseDao = $this->container->get('dao.license');
1103 
1104  $uploadId = intval($args['id']);
1105  $uploadDao = $this->restHelper->getUploadDao();
1106  $query = $request->getQueryParams();
1107  $selectedAgentId = $query['agentId'] ?? null;
1108 
1109  $this->uploadAccessible($uploadId);
1110 
1111  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1112  throw new HttpNotFoundException("Agent does not exist.");
1113  }
1114 
1115  $scannerAgents = array_keys($this->agentNames);
1116  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1117  $scanJobProxy->createAgentStatus($scannerAgents);
1118  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1119  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1120  $editedLicenses = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1121  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1122  $scannedLicenses = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1123  $allScannerLicenseNames = array_keys($scannedLicenses);
1124  $allEditedLicenseNames = array_keys($editedLicenses);
1125  $allLicNames = array_unique(array_merge($allScannerLicenseNames, $allEditedLicenseNames));
1126  $realLicNames = array_diff($allLicNames, array(LicenseDao::NO_LICENSE_FOUND));
1127  $totalScannerLicenseCount = 0;
1128  $editedTotalLicenseCount = 0;
1129 
1130  $res = array();
1131  foreach ($realLicNames as $licenseShortName) {
1132  $count = 0;
1133  if (array_key_exists($licenseShortName, $scannedLicenses)) {
1134  $count = $scannedLicenses[$licenseShortName]['unique'];
1135  $rfId = $scannedLicenses[$licenseShortName]['rf_pk'];
1136  } else {
1137  $rfId = $editedLicenses[$licenseShortName]['rf_pk'];
1138  }
1139  $editedCount = array_key_exists($licenseShortName, $editedLicenses) ? $editedLicenses[$licenseShortName]['count'] : 0;
1140  $totalScannerLicenseCount += $count;
1141  $editedTotalLicenseCount += $editedCount;
1142  $scannerCountLink = $count;
1143  $editedLink = $editedCount;
1144 
1145  $res[] = array($scannerCountLink, $editedLink, array($licenseShortName, $rfId));
1146  }
1147 
1148  $outputArray = [];
1149 
1150  foreach ($res as $item) {
1151  $outputArray[] = [
1152  "id" => intval($item[2][1]),
1153  "name" => $item[2][0],
1154  "scannerCount" => intval($item[0]),
1155  "concludedCount" => intval($item[1]),
1156  ];
1157  }
1158  return $response->withJson($outputArray, 200);
1159  }
1160 
1170  public function getAllAgents($request, $response, $args)
1171  {
1172  $uploadId = intval($args['id']);
1173 
1174  $this->uploadAccessible($uploadId);
1175 
1176  $scannerAgents = array_keys($this->agentNames);
1177  $agentDao = $this->container->get('dao.agent');
1178  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1179  $res = $scanJobProxy->createAgentStatus($scannerAgents);
1180 
1181  $outputArray = [];
1182  foreach ($res as &$item) {
1183  $successfulAgents = [];
1184  if (count($item['successfulAgents']) > 0) {
1185  $item['isAgentRunning'] = false;
1186  } else {
1187  $item['currentAgentId'] = $agentDao->getCurrentAgentRef($item["agentName"])->getAgentId();
1188  $item['currentAgentRev'] = "";
1189  }
1190  foreach ($item['successfulAgents'] as &$agent) {
1191  $successfulAgent = new SuccessfulAgent(intval($agent['agent_id']), $agent['agent_rev'], $agent['agent_name']);
1192  $successfulAgents[] = $successfulAgent->getArray(ApiVersion::getVersion($request));
1193  }
1194  $agent = new Agent($successfulAgents, $item['uploadId'], $item['agentName'], $item['currentAgentId'], $item['currentAgentRev'], $item['isAgentRunning']);
1195  $outputArray[] = $agent->getArray(ApiVersion::getVersion($request));
1196  }
1197  return $response->withJson($outputArray, 200);
1198  }
1199 
1209  public function getEditedLicenses($request, $response, $args)
1210  {
1211  $uploadId = intval($args['id']);
1212 
1213  $this->uploadAccessible($uploadId);
1214 
1215  $clearingDao = $this->container->get('dao.clearing');
1216  $uploadDao = $this->restHelper->getUploadDao();
1217  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1218  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1219  $res = $clearingDao->getClearedLicenseIdAndMultiplicities($itemTreeBounds, $this->restHelper->getGroupId());
1220  $outputArray = [];
1221 
1222  foreach ($res as $key => $value) {
1223  $editedLicense = new EditedLicense(intval($value["rf_pk"]), $key, intval($value["count"]), $value["spdx_id"]);
1224  $outputArray[] = $editedLicense->getArray(ApiVersion::getVersion($request));
1225  }
1226  return $response->withJson($outputArray, 200);
1227  }
1228 
1238  public function getReuseReportSummary($request, $response, $args)
1239  {
1240  $uploadId = intval($args['id']);
1241  $this->uploadAccessible($uploadId);
1242 
1244  $reuseReportProcess = $this->container->get('businessrules.reusereportprocessor');
1245  $res = $reuseReportProcess->getReuseSummary($uploadId);
1246  return $response->withJson($res, 200);
1247  }
1248 
1258  public function getScannedLicenses($request, $response, $args)
1259  {
1260  $uploadId = intval($args['id']);
1261  $query = $request->getQueryParams();
1262  $selectedAgentId = $query['agentId'] ?? null;
1263  $licenseDao = $this->container->get('dao.license');
1264 
1265  $this->uploadAccessible($uploadId);
1266  if ($selectedAgentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $selectedAgentId)) {
1267  throw new HttpNotFoundException("Agent does not exist.");
1268  }
1269  $scannerAgents = array_keys(AgentRef::AGENT_LIST);
1270  $scanJobProxy = new ScanJobProxy($this->agentDao, $uploadId);
1271  $scanJobProxy->createAgentStatus($scannerAgents);
1272  $uploadDao = $this->restHelper->getUploadDao();
1273  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
1274  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
1275  $selectedAgentIds = empty($selectedAgentId) ? $scanJobProxy->getLatestSuccessfulAgentIds() : $selectedAgentId;
1276  $res = $licenseDao->getLicenseHistogram($itemTreeBounds, $selectedAgentIds);
1277  $outputArray = [];
1278 
1279  foreach ($res as $key => $value) {
1280  $scannedLicense = new ScannedLicense($licenseDao->getLicenseByShortName($key)->getId(), $key, $value['count'], $value['unique'], $value['spdx_id']);
1281  $outputArray[] = $scannedLicense->getArray(ApiVersion::getVersion($request));
1282  }
1283  return $response->withJson($outputArray, 200);
1284  }
1294  public function getAgentsRevision($request, $response, $args)
1295  {
1296  $agentDao = $this->container->get('dao.agent');
1297  $uploadId = intval($args['id']);
1298 
1299  $this->uploadAccessible($uploadId);
1300 
1301  $scannerAgents = array_keys($this->agentNames);
1302  $scanJobProxy = new ScanJobProxy($agentDao, $uploadId);
1303  $scanJobProxy->createAgentStatus($scannerAgents);
1304 
1305  $res = array();
1306  foreach ($scanJobProxy->getSuccessfulAgents() as $agent) {
1307  $res[] = array(
1308  "id" => $agent->getAgentId(),
1309  "name" => $agent->getAgentName(),
1310  "revision" => $agent->getAgentRevision(),
1311  );
1312  }
1313  return $response->withJson($res, 200);
1314  }
1315 
1325  public function getTopItem($request, $response, $args)
1326  {
1327  $uploadId = intval($args['id']);
1328  if (!$this->dbHelper->doesIdExist("upload", "upload_pk", $uploadId)) {
1329  $returnVal = new Info(404, "Upload does not exist", InfoType::ERROR);
1330  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
1331  }
1332  $uploadDao = $this->restHelper->getUploadDao();
1333  $itemTreeBounds = $uploadDao->getParentItemBounds($uploadId,
1334  $uploadDao->getUploadtreeTableName($uploadId));
1335  if ($itemTreeBounds === false) {
1336  $error = new Info(500, "Unable to get top item.", InfoType::ERROR);
1337  return $response->withJson($error->getArray(), $error->getCode());
1338  }
1339  $info = new Info(200, $itemTreeBounds->getItemId(), InfoType::INFO);
1340  return $response->withJson($info->getArray(), $info->getCode());
1341  }
1342 }
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