FOSSology  4.4.0
Open Source License Compliance by Open Source Software
DbHelper.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2017 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
12 namespace Fossology\UI\Api\Helper;
13 
14 require_once dirname(dirname(dirname(dirname(__DIR__)))) .
15  "/lib/php/common-db.php";
16 
32 
37 class DbHelper
38 {
43  private $dbManager;
44 
49  private $folderDao;
50 
55  private $uploadDao;
56 
66  {
67  $this->dbManager = $dbManager;
68  $this->folderDao = $folderDao;
69  $this->uploadDao = $uploadDao;
70  }
71 
77  public function getDbManager()
78  {
79  return $this->dbManager;
80  }
81 
97  public function getUploads($userId, $groupId, $limit, $page = 1,
98  $uploadId = null, $options = null, $recursive = true, $apiVersion=ApiVersion::V1)
99  {
100  $uploadProxy = new UploadBrowseProxy($groupId, 0, $this->dbManager);
101  $folderId = $options["folderId"];
102  if ($folderId === null) {
103  $users = $this->getUsers($userId);
104  $folderId = $users[0]->getRootFolderId();
105  }
106  $folders = [$folderId];
107 
108  if ($uploadId !== null) {
109  $recursive = true;
110  $users = $this->getUsers($userId);
111  $folderId = $users[0]->getRootFolderId();
112  $folders = [$folderId];
113  }
114 
115  if ($recursive) {
116  $tree = $this->folderDao->getFolderStructure($folderId);
117  $folders = array_map(function ($folder) {
118  return $folder[$this->folderDao::FOLDER_KEY]->getId();
119  }, $tree);
120  }
121 
122  $params = [$folders];
123  $partialQuery = $uploadProxy->getFolderPartialQuery($params);
124 
125  $where = "";
126  $statementCount = __METHOD__ . ".countAllUploads";
127  $statementGet = __METHOD__ . ".getAllUploads.$limit";
128  if ($uploadId !== null) {
129  $params[] = $uploadId;
130  $where .= " AND upload.upload_pk = $" . count($params);
131  $statementGet .= ".upload";
132  $statementCount .= ".upload";
133  }
134  if (! empty($options["name"])) {
135  $params[] = strtolower("%" . $options["name"] . "%");
136  $where .= " AND (LOWER(upload_desc) LIKE $" . count($params) .
137  " OR LOWER(ufile_name) LIKE $" . count($params) .
138  " OR LOWER(upload_filename) LIKE $" . count($params) . ")";
139  $statementGet .= ".name";
140  $statementCount .= ".name";
141  }
142  if (! empty($options["status"])) {
143  $params[] = $options["status"];
144  $where .= " AND status_fk = $" . count($params);
145  $statementGet .= ".stat";
146  $statementCount .= ".stat";
147  }
148  if (! empty($options["assignee"])) {
149  $params[] = $options["assignee"];
150  $where .= " AND assignee = $" . count($params);
151  $statementGet .= ".assi";
152  $statementCount .= ".assi";
153  }
154  if (! empty($options["since"])) {
155  $params[] = $options["since"];
156  $where .= " AND upload_ts >= to_timestamp($" . count($params) . ")";
157  $statementGet .= ".since";
158  $statementCount .= ".since";
159  }
160  $sql = "SELECT count(*) AS cnt FROM $partialQuery $where;";
161  $totalResult = $this->dbManager->getSingleRow($sql, $params, $statementCount);
162  $totalResult = intval($totalResult['cnt']);
163  $totalResult = intval(ceil($totalResult / $limit));
164 
165  $params[] = ($page - 1) * $limit;
166 
167  $sql = "SELECT
168 upload.upload_pk, upload.upload_desc, upload.upload_ts, upload.upload_filename, upload_clearing.assignee
169 FROM $partialQuery $where ORDER BY upload_pk ASC LIMIT $limit OFFSET $" .
170  count($params) . ";";
171  $results = $this->dbManager->getRows($sql, $params, $statementGet);
172  $uploads = [];
173  foreach ($results as $row) {
174  $uploadId = $row["upload_pk"];
175  $pfile_size = null;
176  $pfile_sha1 = null;
177  $pfile_md5 = null;
178  $pfile_sha256 = null;
179  $pfile = $this->getPfileInfoForUpload($uploadId);
180  if ($pfile !== null) {
181  $pfile_size = $pfile['pfile_size'];
182  $pfile_sha1 = $pfile['pfile_sha1'];
183  $pfile_md5 = $pfile['pfile_md5'];
184  $pfile_sha256 = $pfile['pfile_sha256'];
185  }
186 
187  $folder = $this->getFolderForUpload($uploadId);
188  if ($folder === null) {
189  continue;
190  }
191  $folderId = $folder->getId();
192  $folderName = $folder->getName();
193 
194  $hash = new Hash($pfile_sha1, $pfile_md5, $pfile_sha256, $pfile_size);
195  $upload = new Upload($folderId, $folderName, $uploadId,
196  $row["upload_desc"], $row["upload_filename"], $row["upload_ts"], $row["assignee"], $hash);
197  if (! empty($row["assignee"]) && $row["assignee"] != 1) {
198  $upload->setAssigneeDate($this->uploadDao->getAssigneeDate($uploadId));
199  }
200  $upload->setClosingDate($this->uploadDao->getClosedDate($uploadId));
201  $uploads[] = $upload->getArray($apiVersion);
202  }
203  return [$totalResult, $uploads];
204  }
205 
212  public function getFilenameFromUploadTree($uploadTreePk)
213  {
214  return $this->dbManager->getSingleRow(
215  "SELECT DISTINCT ufile_name FROM uploadtree
216 WHERE uploadtree_pk=$1", [$uploadTreePk])["ufile_name"];
217  }
218 
227  public function doesIdExist($tableName, $idRowName, $id)
228  {
229  return (0 < (intval($this->getDbManager()->getSingleRow("SELECT COUNT(*)
230 FROM $tableName WHERE $idRowName = $1", [$id],
231  __METHOD__ . $tableName . $idRowName)["count"])));
232  }
233 
239  public function deleteUser($id)
240  {
241  require_once dirname(dirname(__DIR__)) . "/user-del-helper.php";
242  deleteUser($id, $this->getDbManager());
243  }
244 
252  public function getUsers($id = null)
253  {
254  if ($id == null) {
255  $usersSQL = "SELECT user_pk, user_name, user_desc, user_email,
256  email_notify, root_folder_fk, group_fk, user_perm, user_agent_list, default_bucketpool_fk FROM users;";
257  $statement = __METHOD__ . ".getAllUsers";
258  } else {
259  $usersSQL = "SELECT user_pk, user_name, user_desc, user_email,
260  email_notify, root_folder_fk, group_fk, user_perm, user_agent_list, default_bucketpool_fk FROM users
261  WHERE user_pk = $1;";
262  $statement = __METHOD__ . ".getSpecificUser";
263  }
264  $users = [];
265  if ($id === null) {
266  $result = $this->dbManager->getRows($usersSQL, [], $statement);
267  } else {
268  $result = $this->dbManager->getRows($usersSQL, [$id], $statement);
269  }
270  $currentUser = Auth::getUserId();
271  $userIsAdmin = Auth::isAdmin();
272  foreach ($result as $row) {
273  $user = null;
274  if ($userIsAdmin ||
275  ($row["user_pk"] == $currentUser)) {
276  $user = new User($row["user_pk"], $row["user_name"], $row["user_desc"],
277  $row["user_email"], $row["user_perm"], $row["root_folder_fk"],
278  $row["email_notify"], $row["user_agent_list"], $row["group_fk"], $row["default_bucketpool_fk"]);
279  } else {
280  $user = new User($row["user_pk"], $row["user_name"], $row["user_desc"],
281  null, null, null, null, null, null);
282  }
283  $users[] = $user;
284  }
285 
286  return $users;
287  }
288 
289 
296  private function getJobStatusCteSQLStatement()
297  {
298  return "WITH job_with_status_cte AS (
299  SELECT j.job_pk, j.job_queued, j.job_name, j.job_upload_fk, j.job_user_fk, j.job_group_fk,
300  CASE
301  WHEN COUNT(CASE WHEN jq.jq_endtext = 'Failed' THEN 1 END) > 0 THEN 'Failed'
302  WHEN COUNT(CASE WHEN jq.jq_endtext in ('Started', 'Restarted', 'Paused') THEN 1 END) > 0 THEN 'Processing'
303  WHEN COUNT(CASE WHEN jq.jq_endtext IS NULL THEN 1 END) > 0 THEN 'Queued'
304  ELSE 'Completed'
305  END AS job_status
306  FROM job j
307  LEFT JOIN jobqueue jq ON j.job_pk=jq.jq_job_fk
308  GROUP BY j.job_pk, j.job_queued, j.job_name, j.job_upload_fk, j.job_user_fk, j.job_group_fk
309  )";
310  }
311 
328  public function getJobs($id = null, $status = null, $sort = "ASC", $limit = 0, $page = 1, $uploadId = null, $userId = null)
329  {
330  $jobsWithStatusCteSQL = $this->getJobStatusCteSQLStatement();
331  $jobSQL = "$jobsWithStatusCteSQL SELECT * FROM job_with_status_cte";
332  $totalJobSql = "$jobsWithStatusCteSQL SELECT count(*) AS cnt FROM job_with_status_cte";
333 
334  $pagination = "";
335  $params = [];
336  $filter = [];
337  $statement = $userId !== null ? __METHOD__ . ".getUserJobs" : __METHOD__ . ".getJobs";
338  $countStatement = __METHOD__ . ".getJobCount";
339 
340  if ($id !== null) {
341  $params[] = $id;
342  $filter[] = "job_pk = $" . count($params);
343  $statement .= ".withJobFilter";
344  $countStatement .= ".withJobFilter";
345  } elseif ($uploadId !== null) {
346  $params[] = $uploadId;
347  $filter[] = "job_upload_fk = $" . count($params);
348  $statement .= ".withUploadFilter";
349  $countStatement .= ".withUploadFilter";
350  }
351 
352  // if userId was given, add it to the where filter
353  if ($userId !== null) {
354  $params[] = $userId;
355  $filter[] = "job_user_fk = $" . count($params);
356  }
357 
358  // if status was given, add it to the where filter
359  if ($status !== null && in_array($status, ["Failed", "Processing", "Queued", "Completed"])) {
360  $params[] = $status;
361  $filter[] = "job_status = $" . count($params);
362  }
363  // build where filter query
364  $filterSQL = $filter ? "WHERE " . implode(" AND ", $filter) : "";
365 
366  // get result for total count
367  $result = $this->dbManager->getSingleRow("$totalJobSql $filterSQL;", $params,
368  $countStatement);
369  $totalResult = $result['cnt'];
370 
371  // sort results in given order, make sure only "ASC" and "DESC" are accepted
372  $sort = strtoupper($sort);
373  $orderBy = in_array($sort, ["ASC", "DESC"]) ? "ORDER BY job_queued $sort" : "";
374 
375  $offset = ($page - 1) * $limit;
376  if ($limit > 0) {
377  $params[] = $limit;
378  $pagination = "LIMIT $" . count($params);
379  $params[] = $offset;
380  $pagination .= " OFFSET $" . count($params);
381  $statement .= ".withLimit";
382  $totalResult = ceil($totalResult / $limit);
383  } else {
384  $totalResult = 1;
385  }
386 
387  // get result for jobs
388  $jobs = [];
389  $result = $this->dbManager->getRows("$jobSQL $filterSQL $orderBy $pagination;", $params,
390  $statement);
391  foreach ($result as $row) {
392  $job = new Job($row["job_pk"]);
393  $job->setName($row["job_name"]);
394  $job->setQueueDate($row["job_queued"]);
395  $job->setUploadId($row["job_upload_fk"]);
396  $job->setUserId($row["job_user_fk"]);
397  $job->setGroupId($row["job_group_fk"]);
398  $job->setStatus($row["job_status"]);
399  $jobs[] = $job;
400  }
401  return [$jobs, $totalResult];
402  }
403 
417  public function getUserJobs($userId = null, $status = null, $sort = "ASC", $limit = 0, $page = 1)
418  {
419  return $this->getJobs(null, $status, $sort, $limit, $page, null, $userId);
420  }
421 
429  public function getTokenKey($tokenId)
430  {
431  $sql = "SELECT token_key, client_id, created_on, expire_on, user_fk, active, token_scope " .
432  "FROM personal_access_tokens WHERE pat_pk = $1;";
433  return $this->dbManager->getSingleRow($sql, [$tokenId],
434  __METHOD__ . ".getTokenSecret");
435  }
436 
442  public function invalidateToken($tokenId)
443  {
444  $sql = "UPDATE personal_access_tokens SET active = false WHERE pat_pk = $1;";
445  $this->dbManager->getSingleRow($sql, [$tokenId], __METHOD__ . ".invalidateToken");
446  }
447 
463  public function insertNewTokenKey($userId, $expire, $scope, $name, $key)
464  {
465  if (! $this->checkTokenNameUnique($userId, $name)) {
466  throw new DuplicateTokenNameException(
467  "Already have a token with same name.", 409);
468  }
469  if (! $this->checkTokenKeyUnique($userId, $name)) {
470  throw new DuplicateTokenKeyException();
471  }
472  $sql = "INSERT INTO personal_access_tokens " .
473  "(user_fk, created_on, expire_on, token_scope, token_name, token_key, active) " .
474  "VALUES ($1, NOW(), $2, $3, $4, $5, true) " .
475  "RETURNING pat_pk || '.' || user_fk AS jti, created_on";
476  return $this->dbManager->getSingleRow($sql, [
477  $userId, $expire, $scope, $name, $key
478  ], __METHOD__ . ".insertNewToken");
479  }
480 
489  public function addNewClient($name, $userId, $clientId, $scope)
490  {
491  $sql = "INSERT INTO personal_access_tokens" .
492  "(user_fk, created_on, token_scope, token_name, client_id, active)" .
493  "VALUES ($1, NOW(), $2, $3, $4, true);";
494  $this->dbManager->getSingleRow($sql, [
495  $userId, $scope, $name, $clientId
496  ], __METHOD__);
497  }
498 
507  private function checkTokenNameUnique($userId, $tokenName)
508  {
509  $tokenIsUnique = true;
510  $sql = "SELECT count(*) AS cnt FROM personal_access_tokens " .
511  "WHERE user_fk = $1 AND token_name = $2;";
512  $result = $this->dbManager->getSingleRow($sql, [$userId, $tokenName],
513  __METHOD__ . ".checkTokenNameUnique");
514  if ($result['cnt'] != 0) {
515  $tokenIsUnique = false;
516  }
517  return $tokenIsUnique;
518  }
519 
528  private function checkTokenKeyUnique($userId, $tokenKey)
529  {
530  $tokenIsUnique = true;
531  $sql = "SELECT count(*) AS cnt FROM personal_access_tokens " .
532  "WHERE user_fk = $1 AND token_key = $2;";
533  $result = $this->dbManager->getSingleRow($sql, [$userId, $tokenKey],
534  __METHOD__ . ".checkTokenKeyUnique");
535  if ($result['cnt'] != 0) {
536  $tokenIsUnique = false;
537  }
538  return $tokenIsUnique;
539  }
540 
546  public function getMaxTokenValidity()
547  {
548  $sql = "SELECT conf_value FROM sysconfig WHERE variablename = $1;";
549  $result = $this->dbManager->getSingleRow($sql, ["PATMaxExipre"],
550  __METHOD__ . ".tokenMaxValidFromSysconfig");
551  $validity = 30;
552  if (! empty($result['conf_value'])) {
553  $validity = intval($result['conf_value']);
554  }
555  return $validity;
556  }
557 
563  public function getPfileInfoForUpload($uploadId)
564  {
565  $sql = "SELECT pfile.* FROM upload INNER JOIN pfile " .
566  "ON pfile_fk = pfile_pk WHERE upload_pk = $1;";
567  $result = $this->dbManager->getSingleRow($sql, [$uploadId],
568  __METHOD__ . ".getPfileFromUpload");
569  if (! empty($result)) {
570  return $result;
571  }
572  return null;
573  }
574 
580  private function getFolderForUpload($uploadId)
581  {
582  $contentId = $this->folderDao->getFolderContentsId($uploadId,
583  $this->folderDao::MODE_UPLOAD);
584  $content = $this->folderDao->getContent($contentId);
585  return $this->folderDao->getFolder($content['parent_fk']);
586  }
587 
598  public function getLicensesPaginated($page, $limit, $kind, $groupId, $active)
599  {
600  $statementName = __METHOD__;
601  $rfTable = 'license_all';
602  $options = ['columns' => ['rf_pk', 'rf_shortname', 'rf_fullname', 'rf_text',
603  'rf_url', 'rf_risk', 'group_fk']];
604  if ($active) {
605  $options['extraCondition'] = "rf_active = '" .
606  $this->dbManager->booleanToDb($active) . "'";
607  }
608  if ($kind == "candidate") {
609  $options['diff'] = true;
610  } elseif ($kind == "main") {
611  $groupId = 0;
612  }
613  $licenseViewDao = new LicenseViewProxy($groupId, $options, $rfTable);
614  $withCte = $licenseViewDao->asCTE();
615 
616  return $this->dbManager->getRows($withCte .
617  " SELECT * FROM $rfTable ORDER BY LOWER(rf_shortname) " .
618  "LIMIT $1 OFFSET $2;",
619  [$limit, ($page - 1) * $limit], $statementName);
620  }
621 
629  public function getLicenseCount($kind, $groupId)
630  {
631  $sql = "SELECT sum(cnt) AS total FROM (";
632  $mainLicSql = " SELECT count(*) AS cnt FROM ONLY license_ref ";
633  $candidateLicSql = " SELECT count(*) AS cnt FROM license_candidate WHERE group_fk = $1";
634  $params = [];
635 
636  if ($kind == "main") {
637  $sql .= $mainLicSql;
638  } elseif ($kind == "candidate") {
639  $sql .= $candidateLicSql;
640  $params[] = $groupId;
641  } else {
642  $sql .= $mainLicSql . " UNION ALL " . $candidateLicSql;
643  $params[] = $groupId;
644  }
645  $sql .= ") as all_lic;";
646 
647  $statement = __METHOD__ . ".getLicenseCount.$kind";
648  $result = $this->dbManager->getSingleRow($sql, $params, $statement);
649  return intval($result['total']);
650  }
651 
652  /*
653  * Get the OAuth token ID from a client id
654  *
655  * @param string $clientId Client ID to get info for
656  * @return integer Token ID
657  */
658  public function getTokenIdFromClientId($clientId)
659  {
660  $sql = "SELECT pat_pk FROM personal_access_tokens " .
661  "WHERE client_id = $1;";
662  $result = $this->dbManager->getSingleRow($sql, [$clientId], __METHOD__);
663  if (!empty($result)) {
664  return $result['pat_pk'];
665  }
666  return null;
667  }
668 }
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
static getUserId()
Get the current user's id.
Definition: Auth.php:68
static isAdmin()
Check if user is admin.
Definition: Auth.php:92
Exception when a token has duplicate key for same user.
Exception when a token has duplicate name for same user.
Provides helper methods to access database for REST api.
Definition: DbHelper.php:38
getJobs($id=null, $status=null, $sort="ASC", $limit=0, $page=1, $uploadId=null, $userId=null)
Get the recent jobs.
Definition: DbHelper.php:328
checkTokenKeyUnique($userId, $tokenKey)
Definition: DbHelper.php:528
getFilenameFromUploadTree($uploadTreePk)
Definition: DbHelper.php:212
getLicensesPaginated($page, $limit, $kind, $groupId, $active)
Definition: DbHelper.php:598
doesIdExist($tableName, $idRowName, $id)
Definition: DbHelper.php:227
addNewClient($name, $userId, $clientId, $scope)
Definition: DbHelper.php:489
getLicenseCount($kind, $groupId)
Definition: DbHelper.php:629
getUserJobs($userId=null, $status=null, $sort="ASC", $limit=0, $page=1)
Get the recent jobs created by an user.
Definition: DbHelper.php:417
checkTokenNameUnique($userId, $tokenName)
Definition: DbHelper.php:507
insertNewTokenKey($userId, $expire, $scope, $name, $key)
Definition: DbHelper.php:463
__construct(DbManager $dbManager, FolderDao $folderDao, UploadDao $uploadDao)
Definition: DbHelper.php:64
getUploads($userId, $groupId, $limit, $page=1, $uploadId=null, $options=null, $recursive=true, $apiVersion=ApiVersion::V1)
Definition: DbHelper.php:97
Hash model holding information about file like checksums and size.
Definition: Hash.php:18
Model class to hold Upload info.
Definition: Upload.php:17
Model to hold user information.
Definition: User.php:21
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
FUNCTION char * strtoupper(char *s)
Helper function to upper case a string.
Definition: utils.c:39
REST api helper classes.