FOSSology  4.4.0
Open Source License Compliance by Open Source Software
UploadTreeController.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2023 Samuel Dushimimana <dushsam100@gmail.com>
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
13 namespace Fossology\UI\Api\Controllers;
14 
36 use Psr\Http\Message\ServerRequestInterface;
37 use Symfony\Component\HttpFoundation\Response;
38 
44 {
46  private $clearingDao;
47 
52  private $licenseDao;
53 
58  private $highlightDao;
59 
61  private $clearingDecisionEventProcessor;
62 
67  private $decisionTypes;
68 
69 
70  public function __construct($container)
71  {
72  parent::__construct($container);
73  $this->clearingDao = $this->container->get('dao.clearing');
74  $this->licenseDao = $this->container->get('dao.license');
75  $this->highlightDao = $this->container->get("dao.highlight");
76  $this->clearingDecisionEventProcessor = $this->container->get('businessrules.clearing_decision_processor');
77  $this->decisionTypes = $this->container->get('decision.types');
78  }
79 
89  public function viewLicenseFile($request, $response, $args)
90  {
91  $uploadId = intval($args['id']);
92  $itemId = intval($args['itemId']);
93 
94  $this->uploadAccessible($uploadId);
95  $this->isItemExists($uploadId, $itemId);
96 
98  $view = $this->restHelper->getPlugin('view');
99 
100  $inputFile = @fopen(RepPathItem($itemId), "rb");
101  if (empty($inputFile)) {
102  global $Plugins;
103  $reunpackPlugin = &$Plugins[plugin_find_id("ui_reunpack")];
104  $state = $reunpackPlugin->CheckStatus($uploadId, "reunpack", "ununpack");
105  if ($state != 0 && $state != 2) {
106  $errorMess = _("Reunpack job is running: you can see it in");
107  } else {
108  $errorMess = _("File contents are not available in the repository.");
109  }
110  throw new HttpInternalServerErrorException($errorMess);
111  }
112  rewind($inputFile);
113 
114  $res = $view->getText($inputFile, 0, 0, -1, null, false, true);
115  $response->getBody()->write($res);
116  return $response->withHeader("Content-Type", "text/plain")
117  ->withHeader("Cache-Control", "max-age=1296000, must-revalidate")
118  ->withHeader("Etag", md5($response->getBody()));
119  }
120 
130  public function setClearingDecision($request, $response, $args)
131  {
132  $uploadId = intval($args['id']);
133  $this->uploadAccessible($uploadId);
134 
135  $body = $this->getParsedBody($request);
136  $decisionType = $body['decisionType'];
137  $global = $body['globalDecision'];
138 
139  // check if the given globalDecision value is a boolean
140  if ($global !== null && !is_bool($global)) {
141  throw new HttpBadRequestException("GlobalDecision should be a boolean");
142  }
143 
144  $uploadTreeId = intval($args['itemId']);
145 
146  // check if the given key exists in the known decision types
147  if (!array_key_exists($decisionType, $this->decisionTypes->getMap())) {
148  throw new HttpBadRequestException(
149  "Decision Type should be one of the following keys: " .
150  implode(", ", array_keys($this->decisionTypes->getMap())));
151  }
152  $this->isItemExists($uploadId, $uploadTreeId);
153 
155  $viewLicensePlugin = $this->restHelper->getPlugin('view-license');
156  $_GET['clearingTypes'] = $decisionType;
157  $_GET['globalDecision'] = $global ? 1 : 0;
158  $viewLicensePlugin->updateLastItem($this->restHelper->getUserId(), $this->restHelper->getGroupId(), $uploadTreeId, $uploadTreeId);
159  $returnVal = new Info(200, "Successfully set decision", InfoType::INFO);
160  return $response->withJson($returnVal->getArray(), $returnVal->getCode());
161  }
162 
172  public function getNextPreviousItem($request, $response, $args)
173  {
174  $uploadTreeId = intval($args['itemId']);
175  $uploadId = intval($args['id']);
176  $query = $request->getQueryParams();
177  $uploadDao = $this->restHelper->getUploadDao();
178  $selection = "";
179 
180  $this->uploadAccessible($uploadId);
181  $this->isItemExists($uploadId, $uploadTreeId);
182 
183  if ($query['selection'] !== null) {
184  $selection = $query['selection'];
185  if ($selection != "withLicenses" && $selection != "noClearing") {
186  throw new HttpBadRequestException(
187  "selection should be either 'withLicenses' or 'noClearing'");
188  }
189  }
190 
191  $options = array('skipThese' => $selection == "withLicenses" ? "noLicense" : ($selection == "noClearing" ? "alreadyCleared" : ""), 'groupId' => $this->restHelper->getGroupId());
192 
193  $prevItem = $uploadDao->getPreviousItem($uploadId, $uploadTreeId, $options);
194  $prevItemId = $prevItem ? $prevItem->getId() : null;
195 
196  $nextItem = $uploadDao->getNextItem($uploadId, $uploadTreeId, $options);
197  $nextItemId = $nextItem ? $nextItem->getId() : null;
198 
199  $res = [
200  "prevItemId" => $prevItemId,
201  "nextItemId" => $nextItemId
202  ];
203  return $response->withJson($res, 200);
204  }
205 
215  public function getBulkHistory($request, $response, $args)
216  {
217  $uploadTreeId = intval($args['itemId']);
218  $uploadId = intval($args['id']);
219  $uploadDao = $this->restHelper->getUploadDao();
220  $clearingDao = $this->container->get('dao.clearing');
221 
222  $this->uploadAccessible($uploadId);
223  $this->isItemExists($uploadId, $uploadTreeId);
224 
225  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
226  $itemTreeBounds = $uploadDao->getItemTreeBounds($uploadTreeId, $uploadTreeTableName);
227 
228  $res = $clearingDao->getBulkHistory($itemTreeBounds, $this->restHelper->getGroupId());
229  $updatedRes = [];
230 
231  foreach ($res as $value) {
232  $obj = new BulkHistory(
233  intval($value['bulkId']),
234  intval($value['id']),
235  $value['text'],
236  $value['matched'],
237  $value['tried'],
238  $value['addedLicenses'],
239  $value['removedLicenses']);
240  $updatedRes[] = $obj->getArray();
241  }
242  return $response->withJson($updatedRes, 200);
243  }
244 
254  public function getClearingHistory($request, $response, $args)
255  {
256  $itemId = intval($args['itemId']);
257  $uploadId = intval($args['id']);
258  $uploadDao = $this->restHelper->getUploadDao();
259  $clearingDao = $this->container->get('dao.clearing');
260 
261  $this->uploadAccessible($uploadId);
262  $this->isItemExists($uploadId, $itemId);
263 
264  $itemTreeBounds = $uploadDao->getItemTreeBoundsFromUploadId($itemId, $uploadId);
265  $clearingDecWithLicenses = $clearingDao->getFileClearings($itemTreeBounds, $this->restHelper->getGroupId(), false, true);
266 
267  $data = [];
268  $scope = new DecisionScopes();
269 
270  foreach ($clearingDecWithLicenses as $clearingDecision) {
271  $removedLicenses = [];
272  $addedLicenses = [];
273 
274  foreach ($clearingDecision->getClearingLicenses() as $lic) {
275  $shortName = $lic->getShortName();
276  $lic->isRemoved() ? $removedLicenses[] = $shortName : $addedLicenses[] = $shortName;
277  }
278  ksort($removedLicenses, SORT_STRING);
279  ksort($addedLicenses, SORT_STRING);
280  $obj = new ClearingHistory(
281  date('Y-m-d', $clearingDecision->getTimeStamp()),
282  $clearingDecision->getUserName(),
283  $scope->getTypeName($clearingDecision->getScope()),
284  $this->decisionTypes->getConstantNameFromKey($clearingDecision->getType()),
285  $addedLicenses, $removedLicenses);
286  $data[] = $obj->getArray();
287  }
288  return $response->withJson($data, 200);
289  }
290 
300  public function getHighlightEntries($request, $response, $args)
301  {
302  $uploadTreeId = intval($args['itemId']);
303  $uploadId = intval($args['id']);
304  $query = $request->getQueryParams();
305  $uploadDao = $this->restHelper->getUploadDao();
306 
307  $this->uploadAccessible($uploadId);
308  $this->isItemExists($uploadId, $uploadTreeId);
309 
310  $agentId = $query['agentId'] ?? null;
311  $highlightId = $query['highlightId'] ?? null;
312  $licenseId = $query['licenseId'] ?? null;
313  $clearingId = $query['clearingId'] ?? null;
314 
315  if ($licenseId !== null && !$this->dbHelper->doesIdExist("license_ref", "rf_pk", $licenseId)) {
316  throw new HttpNotFoundException("License does not exist");
317  }
318  if ($highlightId !== null && !$this->dbHelper->doesIdExist("highlight", "fl_fk", $highlightId)) {
319  throw new HttpNotFoundException("Highlight does not exist");
320  }
321  if ($agentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $agentId)) {
322  throw new HttpNotFoundException("Agent does not exist");
323  }
324  if ($clearingId !== null && !$this->dbHelper->doesIdExist("clearing_event", "clearing_event_pk", $clearingId)) {
325  throw new HttpNotFoundException("Clearing does not exist");
326  }
327 
328  $uploadTreeTableName = $uploadDao->getUploadtreeTableName($uploadId);
329  $itemTreeBounds = $uploadDao->getItemTreeBounds($uploadTreeId, $uploadTreeTableName);
331  $viewLicensePlugin = $this->restHelper->getPlugin('view-license');
332  $res = $viewLicensePlugin->getSelectedHighlighting($itemTreeBounds, $licenseId,
333  $agentId, $highlightId, $clearingId, $uploadId);
334 
335  $transformedRes = [];
336  foreach ($res as $value) {
337  $transformedRes[] = $value->getArray();
338  }
339  return $response->withJson($transformedRes, 200);
340  }
341 
351  public function getTreeView($request, $response, $args)
352  {
353  $uploadTreeId = intval($args['itemId']);
354  $uploadId = intval($args['id']);
355  $query = $request->getQueryParams();
356  $agentId = $query['agentId'] ?? null;
357  $flatten = $query['flatten'] ?? null;
358  $scanFilter = $query['scanLicenseFilter'] ?? null;
359  $editedFilter = $query['editedLicenseFilter'] ?? null;
360  $sortDir = $query['sort'] ?? null;
361  if (ApiVersion::getVersion($request) == ApiVersion::V2) {
362  $page = $query['page'] ?? null;
363  $limit = $query['limit'] ?? null;
364  } else {
365  $page = $request->getHeaderLine('page');
366  $limit = $request->getHeaderLine('limit');
367  }
368  $tagId = $query['tagId'] ?? null;
369  $sSearch = $query['search'] ?? null;
370  $openCBoxFilter = $query['filterOpen'] ?? null;
371  $show = ($query['showQuick'] !== null && $query['showQuick'] !== 'false') ? true : null;
372  $licenseDao = $this->container->get('dao.license');
373 
374  $uploadDao = $this->restHelper->getUploadDao();
375 
376  $this->uploadAccessible($uploadId);
377  $this->isItemExists($uploadId, $uploadTreeId);
378 
379  if ($agentId !== null && !$this->dbHelper->doesIdExist("agent", "agent_pk", $agentId)) {
380  throw new HttpNotFoundException("Agent does not exist");
381  }
382  if ($tagId !== null && !$this->dbHelper->doesIdExist("tag", "tag_pk", $tagId)) {
383  throw new HttpNotFoundException("Tag does not exist");
384  }
385  if ($openCBoxFilter !== null && ($openCBoxFilter !== 'true' && $openCBoxFilter !== 'false')) {
386  throw new HttpBadRequestException("openCBoxFilter must be a boolean value");
387  }
388  if ($flatten !== null && ($flatten !== 'true' && $flatten !== 'false')) {
389  throw new HttpBadRequestException("flatten must be a boolean value");
390  }
391  if ($sortDir != null && !($sortDir == "asc" || $sortDir == "desc")) {
392  throw new HttpBadRequestException("sortDirection must be asc or desc");
393  }
394  if ($page != null && (!is_numeric($page) || intval($page) < 1)) {
395  throw new HttpBadRequestException("page should be positive integer Greater or Equal to 1");
396  }
397  if ($show != null && $show != 'true' && $show != 'false') {
398  throw new HttpBadRequestException("show must be a boolean value");
399  }
400  if ($limit != null && (!is_numeric($limit) || intval($limit) < 1)) {
401  throw new HttpBadRequestException("limit should be positive integer Greater or Equal to 1");
402  }
403  $queryKeys = array_keys($query);
404  $allowedKeys = ['showQuick', 'agentId', 'flatten', 'scanLicenseFilter', 'editedLicenseFilter', 'sort', 'tagId', 'search', 'filterOpen'];
405  $diff = array_diff($queryKeys, $allowedKeys);
406  if (count($diff) > 0) {
407  throw new HttpBadRequestException("Invalid query parameter(s) : " . implode(",", $diff));
408  }
409 
410  if ($editedFilter !== null) {
411  $license = $licenseDao->getLicenseByShortName($editedFilter, $this->restHelper->getGroupId());
412  if ($license === null) {
413  throw new HttpNotFoundException("Edited License filter $editedFilter does not exist");
414  }
415  $editedFilter = $license->getId();
416  }
417 
418  if ($scanFilter !== null) {
419  $license = $licenseDao->getLicenseByShortName($scanFilter, $this->restHelper->getGroupId());
420  if ($license === null) {
421  throw new HttpNotFoundException("Scan License filter $scanFilter does not exist");
422  }
423  $scanFilter = $license->getId();
424  }
425 
426  if ($page == null) {
427  $page = 1;
428  }
429  if ($limit == null) {
430  $limit = 50;
431  }
432 
433  if ($show) {
434  $uploadTreeId = $uploadDao->getFatItemId($uploadTreeId, $uploadId, $uploadDao->getUploadtreeTableName($uploadId));
435  }
436 
438  $ajaxExplorerPlugin = $this->restHelper->getPlugin('ajax_explorer');
439  $symfonyRequest = new \Symfony\Component\HttpFoundation\Request();
440  $symfonyRequest->request->set('agentId', $agentId);
441  $symfonyRequest->request->set('tag', $tagId);
442  $symfonyRequest->request->set('item', $uploadTreeId);
443  $symfonyRequest->request->set('upload', $uploadId);
444  $symfonyRequest->request->set('fromRest', true);
445  $symfonyRequest->request->set('flatten', ($flatten !== null && $flatten !== 'false') ? true : null);
446  $symfonyRequest->request->set('openCBoxFilter', $openCBoxFilter);
447  $symfonyRequest->request->set('show', $show ? "quick" : null);
448  $symfonyRequest->request->set('iSortingCols', "1");
449  $symfonyRequest->request->set('bSortable_0', "true");
450  $symfonyRequest->request->set('iSortCol_0', "0");
451  $symfonyRequest->request->set('sSortDir_0', $sortDir != null ? $sortDir : 'asc');
452  $symfonyRequest->request->set('iDisplayStart', (intval($page) - 1) * intval($limit));
453  $symfonyRequest->request->set('iDisplayLength', intval($limit));
454  $symfonyRequest->request->set("sSearch", $sSearch);
455  $symfonyRequest->request->set("conFilter", $editedFilter);
456  $symfonyRequest->request->set("scanFilter", $scanFilter);
457 
458  $res = $ajaxExplorerPlugin->handle($symfonyRequest);
459 
460  return $response->withJson(json_decode($res->getContent(), true)["aaData"], 200);
461  }
462 
472  public function getLicenseDecisions($request, $response, $args)
473  {
474  $uploadTreeId = intval($args['itemId']);
475  $uploadPk = intval($args['id']);
476  $uploadDao = $this->restHelper->getUploadDao();
477  $licenses = [];
478 
479  $this->uploadAccessible($uploadPk);
480  $this->isItemExists($uploadPk, $uploadTreeId);
481 
482  $itemTreeBounds = $uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadPk);
483  if ($itemTreeBounds->containsFiles()) {
484  throw new HttpBadRequestException("Item expected to be a file, container sent.");
485  }
486 
487  list ($addedClearingResults, $removedLicenses) = $this->clearingDecisionEventProcessor->getCurrentClearings(
488  $itemTreeBounds, $this->restHelper->getGroupId(), LicenseMap::CONCLUSION);
489  $licenseEventTypes = new ClearingEventTypes();
490 
491  $mergedArray = [];
492 
493  foreach ($addedClearingResults as $item) {
494  $mergedArray[] = ['item' => $item, 'isRemoved' => false];
495  }
496 
497  foreach ($removedLicenses as $item) {
498  $mergedArray[] = ['item' => $item, 'isRemoved' => true];
499  }
500 
501  $mainLicIds = $this->clearingDao->getMainLicenseIds($uploadPk, $this->restHelper->getGroupId());
502 
503  foreach ($mergedArray as $item) {
504  $clearingResult = $item['item'];
505  $licenseShortName = $clearingResult->getLicenseShortName();
506  $licenseId = $clearingResult->getLicenseId();
507 
508  $types = $this->getAgentInfo($clearingResult);
509  $reportInfo = "";
510  $comment = "";
511  $acknowledgement = "";
512 
513  if ($clearingResult->hasClearingEvent()) {
514  $licenseDecisionEvent = $clearingResult->getClearingEvent();
515  $types[] = $this->getEventInfo($licenseDecisionEvent, $licenseEventTypes);
516  $reportInfo = $licenseDecisionEvent->getReportinfo();
517  $comment = $licenseDecisionEvent->getComment();
518  $acknowledgement = $licenseDecisionEvent->getAcknowledgement();
519  }
520 
521  $obligations = $this->licenseDao->getLicenseObligations([$licenseId], false);
522  $obligations = array_merge($obligations, $this->licenseDao->getLicenseObligations([$licenseId], true));
523  $obligationList = [];
524  foreach ($obligations as $obligation) {
525  $obligationList[] = new Obligation(
526  $obligation['ob_pk'],
527  $obligation['ob_topic'],
528  $obligation['ob_type'],
529  $obligation['ob_text'],
530  $obligation['ob_classification'],
531  $obligation['ob_comment']
532  );
533  }
534  $license = $this->licenseDao->getLicenseById($licenseId);
535  $licenseObj = new LicenseDecision(
536  $license->getId(),
537  $licenseShortName,
538  $license->getFullName(),
539  $item['isRemoved'] ? '-' : (!empty($reportInfo) ? $reportInfo : $license->getText()),
540  $license->getUrl(),
541  $types,
542  $item['isRemoved'] ? '-' : $acknowledgement,
543  $item['isRemoved'] ? '-' : $comment,
544  in_array($license->getId(), $mainLicIds),
545  $obligationList,
546  $license->getRisk(),
547  $item['isRemoved']
548  );
549  $licenses[] = $licenseObj->getArray();
550  }
551  return $response->withJson($licenses, 200);
552  }
553 
558  private function getAgentInfo(ClearingResult $licenseDecisionResult)
559  {
560  $agentResults = array();
561  foreach ($licenseDecisionResult->getAgentDecisionEvents() as $agentDecisionEvent) {
562  $agentId = $agentDecisionEvent->getAgentId();
563  $matchId = $agentDecisionEvent->getMatchId();
564  $highlightRegion = $this->highlightDao->getHighlightRegion($matchId);
565  $page = null;
566  $percentage = $agentDecisionEvent->getPercentage();
567  if ($highlightRegion[0] != "" && $highlightRegion[1] != "") {
568  $page = $this->highlightDao->getPageNumberOfHighlightEntry($matchId);
569  }
570  $result = array(
571  'name' => $agentDecisionEvent->getAgentName(),
572  'clearingId' => null,
573  'agentId' => $agentId,
574  'highlightId' => $matchId,
575  'page' => intval($page),
576  'percentage' => $percentage
577  );
578  $agentResults[] = $result;
579  }
580  return $agentResults;
581  }
582 
583  private function getEventInfo($licenseDecisionEvent, $licenseEventTypes)
584  {
585  $type = $licenseEventTypes->getTypeName($licenseDecisionEvent->getEventType());
586  $eventId = null;
587  if ($licenseDecisionEvent->getEventType() == ClearingEventTypes::BULK) {
588  $eventId = $licenseDecisionEvent->getEventId();
589  }
590  return array(
591  'name' => $type,
592  'clearingId' => $eventId,
593  'agentId' => null,
594  'highlightId' => null,
595  'page' => null,
596  'percentage' => null
597  );
598  }
599 
609  public function handleAddEditAndDeleteLicenseDecision($request, $response, $args)
610  {
611  $body = $this->getParsedBody($request);
612  $uploadTreeId = intval($args['itemId']);
613  $uploadId = intval($args['id']);
614  $uploadDao = $this->restHelper->getUploadDao();
615  $errors = [];
616  $success = [];
617 
618  $this->uploadAccessible($uploadId);
619  $this->isItemExists($uploadId, $uploadTreeId);
620 
621  if (empty($body)) {
622  throw new HttpBadRequestException("Request body is missing or empty.");
623  }
624  if (!is_array($body)) {
625  throw new HttpBadRequestException("Request body should be an array.");
626  }
628  $concludeLicensePlugin = $this->restHelper->getPlugin('conclude-license');
629  $res = $concludeLicensePlugin->getCurrentSelectedLicensesTableData($uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId), $this->restHelper->getGroupId(), true);
630 
631  $existingLicenseIds = [];
632  foreach ($res as $license) {
633  $currId = $license['DT_RowId'];
634  $currId = explode(',', $currId)[1];
635  $existingLicenseIds[] = intval($currId);
636  }
637 
638  foreach (array_keys($body) as $index) {
639  $licenseReq = $body[$index];
640 
641  $shortName = $licenseReq['shortName'];
642  if (empty($shortName)) {
643  $error = new Info(400, "Short name missing from the request #" . ($index + 1), InfoType::ERROR);
644  $errors[] = $error->getArray();
645  continue;
646  }
647 
648  $existingLicense = $this->licenseDao->getLicenseByShortName($shortName, $this->restHelper->getGroupId());
649  if ($existingLicense === null) {
650  $error = new Info(404, "License file with short name '$shortName' not found.",
651  InfoType::ERROR);
652  $errors[] = $error->getArray();
653  continue;
654  }
655 
656  if (!isset($licenseReq['add'])) {
657  $error = new Info(400, "'add' property missing from the request #" . ($index + 1), InfoType::ERROR);
658  $errors[] = $error->getArray();
659  continue;
660  }
661 
662  if ($licenseReq['add']) {
663  $columnsToUpdate = [];
664  if (isset($licenseReq['text'])) {
665  $columnsToUpdate[] = [
666  'columnId' => 'reportinfo',
667  'value' => $licenseReq['text']
668  ];
669  }
670  if (isset($licenseReq['ack'])) {
671  $columnsToUpdate[] = [
672  'columnId' => 'acknowledgement',
673  'value' => $licenseReq['ack']
674  ];
675  }
676  if (isset($licenseReq['comment'])) {
677  $columnsToUpdate[] = [
678  'columnId' => 'comment',
679  'value' => $licenseReq['comment']
680  ];
681  }
682 
683  if (in_array($existingLicense->getId(), $existingLicenseIds)) {
684  $valText = "";
685  foreach (array_keys($columnsToUpdate) as $colIdx) {
686  $this->clearingDao->updateClearingEvent($uploadTreeId, $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $existingLicense->getId(), $columnsToUpdate[$colIdx]['columnId'], $columnsToUpdate[$colIdx]['value']);
687  if ($colIdx == count($columnsToUpdate) - 1 && count($columnsToUpdate) > 1) {
688  $valText .= " and ";
689  } else if ($colIdx > 0 && count($columnsToUpdate) > 1) {
690  $valText .= ", ";
691  }
692  $valText .= $columnsToUpdate[$colIdx]['columnId'];
693  }
694  $val = new Info(200, "Successfully updated " . $shortName . "'s license " . $valText, InfoType::INFO);
695  } else {
696  $this->clearingDao->insertClearingEvent($uploadTreeId, $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $existingLicense->getId(), false);
697  foreach (array_keys($columnsToUpdate) as $colIdx) {
698  $this->clearingDao->updateClearingEvent($uploadTreeId, $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $existingLicense->getId(), $columnsToUpdate[$colIdx]['columnId'], $columnsToUpdate[$colIdx]['value']);
699  }
700  $val = new Info(200, "Successfully added " . $shortName . " as a new license decision.", InfoType::INFO);
701  }
702  } else {
703  if (!in_array($existingLicense->getId(), $existingLicenseIds)) {
704  $error = new Info(404, $shortName . " license does not exist on this item", InfoType::ERROR);
705  $errors[] = $error->getArray();
706  continue;
707  }
708  $this->clearingDao->insertClearingEvent($uploadTreeId, $this->restHelper->getUserId(), $this->restHelper->getGroupId(), $existingLicense->getId(), true);
709  $val = new Info(200, "Successfully deleted " . $shortName . " from license decision list.", InfoType::INFO);
710  }
711  $success[] = $val->getArray();
712  }
713 
714  return $response->withJson([
715  'success' => $success,
716  'errors' => $errors
717  ], 200);
718  }
719 
729  public function scheduleBulkScan($request, $response, $args)
730  {
731  $body = $this->getParsedBody($request);
732  $uploadTreeId = intval($args['itemId']);
733  $uploadId = intval($args['id']);
734  $licenseDao = $this->container->get('dao.license');
735 
736  $this->uploadAccessible($uploadId);
737  $this->isItemExists($uploadId, $uploadTreeId);
738 
739  $isValid = true;
740 
741  // Validation errors
742  $errors = [];
743 
744  // Verify if each element from $body was given in the request
745  $requiredFields = ['bulkActions', 'refText', 'bulkScope', 'forceDecision', 'ignoreIrre', 'delimiters', 'scanOnlyFindings'];
746 
747  foreach ($requiredFields as $field) {
748  if (!array_key_exists($field, $body)) {
749  $isValid = false;
750  $errors[] = "$field should be given";
751  }
752  }
753  // Additional validations for specific fields
754  if ($isValid) {
755  // Check if refText is not equal to ""
756  if ($body['refText'] === "") {
757  $isValid = false;
758  $errors[] = "refText should not be empty";
759  }
760  // Check if forceDecision and ignoreIrre are true or false
761  if (!in_array($body['forceDecision'], [true, false]) || !in_array($body['ignoreIrre'], [true, false]) || !in_array($body['scanOnlyFindings'], [true, false])) {
762  $isValid = false;
763  $errors[] = "forceDecision, ignoreIrre and scanOnlyFindings should be either true or false";
764  }
765  // Check if delimiters is a string
766  if (!is_string($body['delimiters'])) {
767  $isValid = false;
768  $errors[] = "delimiters should be a string";
769  }
770  // check if bulkScope value is either folder or upload
771  if (!in_array($body['bulkScope'], ["folder", "upload"])) {
772  $isValid = false;
773  $errors[] = "bulkScope should be either folder or upload";
774  }
775  // check if the bulkActions property is an array and if each element has a valid license id
776  if (!is_array($body['bulkActions'])) {
777  $isValid = false;
778  $errors[] = "bulkActions should be an array";
779  } else {
780  foreach ($body['bulkActions'] as &$license) {
781  $existingLicense = $licenseDao->getLicenseByShortName($license['licenseShortName'],
782  $this->restHelper->getGroupId());
783  if ($existingLicense == null) {
784  $isValid = false;
785  $errors[] = "License with short name " . $license['licenseShortName'] . " does not exist";
786  } else if ($license['licenseAction'] != null && !in_array($license['licenseAction'], ["ADD", "REMOVE"])) {
787  $isValid = false;
788  $errors[] = "License action should be either ADD or REMOVE";
789  }
790 
791  $license['licenseId'] = $existingLicense->getId();
792  $license['reportinfo'] = $license['licenseText'];
793  $license['action'] = $license['licenseAction'] == 'REMOVE' ? 'Remove' : 'Add';
794  }
795  }
796  }
797 
798  $errorMess = "";
799  if (!$isValid) {
800  foreach ($errors as $error) {
801  $errorMess = $error . "\n";
802  }
803  throw new HttpBadRequestException($errorMess);
804  }
805 
806  $symfonyRequest = new \Symfony\Component\HttpFoundation\Request();
807  $symfonyRequest->request->set('bulkAction', $body['bulkActions']);
808  $symfonyRequest->request->set('refText', $body['refText']);
809  $symfonyRequest->request->set('bulkScope', $body['bulkScope'] == "folder" ? 'f' : 'u');
810  $symfonyRequest->request->set('uploadTreeId', $uploadTreeId);
811  $symfonyRequest->request->set('forceDecision', $body['forceDecision'] ? 1 : 0);
812  $symfonyRequest->request->set('ignoreIrre', $body['ignoreIrre'] ? 1 : 0);
813  $symfonyRequest->request->set('delimiters', $body['delimiters']);
814  $symfonyRequest->request->set('scanOnlyFindings', $body['scanOnlyFindings'] ? 1 : 0);
815 
817  $changeLicenseBulk = $this->restHelper->getPlugin('change-license-bulk');
818  $res = $changeLicenseBulk->handle($symfonyRequest);
819  $status = $res->getStatusCode();
820 
821  if ($status != 200) {
822  if ($status == Response::HTTP_BAD_REQUEST) {
823  throw new HttpBadRequestException(
824  json_decode($res->getContent(), true)["error"]);
825  }
826  throw new HttpInternalServerErrorException(
827  json_decode($res->getContent(), true)["error"]);
828  }
829 
830  $info = new Info(201, json_decode($res->getContent(), true)["jqid"], InfoType::INFO);
831  return $response->withJson($info->getArray(), $info->getCode());
832  }
833 }
Utility functions to process ClearingDecision.
Wrapper class for license map.
Definition: LicenseMap.php:19
Base controller for REST calls.
isItemExists(int $uploadId, int $itemId)
getParsedBody(ServerRequestInterface $request)
Parse request body as JSON and return associative PHP array.
getAgentInfo(ClearingResult $licenseDecisionResult)
Override Slim response for withJson function.
static getVersion(ServerRequestInterface $request)
Definition: ApiVersion.php:29
Different type of infos provided by REST.
Definition: InfoType.php:16
Info model to contain general error and return values.
Definition: Info.php:19
RepPathItem($Item, $Repo="files")
Given an uploadtree_pk, retrieve the pfile path.
Definition: common-repo.php:91