GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CheckDbTask::hasPrivilege()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Проверка БД с которой работает движок - доступы, настройки самой БД и т.д.
4
 * @author Fedor A Borshev <[email protected]>
5
 * @link https://github.com/shogodev/argilla/
6
 * @copyright Copyright &copy; 2003-2014 Shogo
7
 * @license http://argilla.ru/LICENSE
8
 * @package build.tasks.checkDbTask
9
 */
10
11
require_once "phing/Task.php";
12
13
class CheckDbTask extends Task
14
{
15
  /**
16
   * @var boolean проверять доступ к триггерам
17
   */
18
  private $checkTriggers;
19
20
  /**
21
   * @var boolean проверять доступ к созданию и просмотру структуры вьюх
22
   */
23
  private $checkViews;
24
25
  /**
26
   * @var boolean проверять доступ к созданию и изменению хранимых процедур
27
   */
28
  private $checkRoutines;
29
30
  /**
31
   * @var boolean проверять доступ к LOCK TABLES
32
   */
33
  private $checkLockTables;
34
35
  /**
36
   * @var boolean проверять доступ к CREATE TMP TABLE
37
   */
38
  private $checkTmpTable;
39
40
  /**
41
   * @var boolean проверять включен ли InnoDB
42
   */
43
  private $checkInnoDb;
44
45
  /**
46
   * @var PDO
47
   */
48
  private $pdo;
49
  /**
50
   * @var bool
51
   */
52
  private $_connected = false;
53
54
  private $_user;
55
  private $_host;
56
  private $_dbName;
57
58
  /**
59
   * @var PrivilegeChecker
60
   */
61
  private $_privilegeChecker;
62
63
  #region setters
64
  public function setTriggers($val)
65
  {
66
    $this->checkTriggers = $val;
67
  }
68
69
  public function setViews($val)
70
  {
71
    $this->checkViews = $val;
72
  }
73
74
  public function setRoutines($val)
75
  {
76
    $this->checkRoutines = $val;
77
  }
78
79
  public function setLockTables($val)
80
  {
81
    $this->checkLockTables = $val;
82
  }
83
84
  public function setTmpTables($val)
85
  {
86
    $this->checkTmpTable = $val;
87
  }
88
89
  public function setInnoDb($val)
90
  {
91
    $this->checkInnoDb = $val;
92
  }
93
94
  #endregion
95
96
  public function main()
97
  {
98
    if( !$this->_connected )
99
    {
100
      $this->connect();
101
    }
102
103
    try
104
    {
105
      $this->_privilegeChecker = new PrivilegeChecker(PrivilegeChecker::getShowGrantsOutput($this->pdo));
106
    }
107
    catch(Exception $e)
108
    {
109
      if( strpos($e->getMessage(), 'The MySQL server is running with the --skip-grant-tables') !== false )
110
      {
111
        return;
112
      }
113
      else
114
      {
115
        throw $e;
116
      }
117
    }
118
119
    if( $this->checkTriggers )
120
    {
121
      $this->checkPrivilege(PrivilegeEnum::TRIGGER);
122
    }
123
124
    if( $this->checkViews )
125
    {
126
      $this->checkPrivilege(PrivilegeEnum::SHOW_VIEW);
127
      $this->checkPrivilege(PrivilegeEnum::CREATE_VIEW);
128
    }
129
130
    if( $this->checkRoutines )
131
    {
132
      $this->checkPrivilege(PrivilegeEnum::CREATE_ROUTINE);
133
      $this->checkPrivilege(PrivilegeEnum::ALTER_ROUTINE);
134
    }
135
136
    if( $this->checkLockTables )
137
    {
138
      $this->checkPrivilege(PrivilegeEnum::LOCK_TABLES);
139
    }
140
141
    if( $this->checkTmpTable )
142
    {
143
      $this->checkPrivilege(PrivilegeEnum::CREATE_TEMPORARY_TABLES);
144
    }
145
146
    if( $this->checkInnoDb )
147
    {
148
      $this->checkEngine('InnoDB');
149
    }
150
  }
151
152
  protected function checkPrivilege($privilege)
153
  {
154
    if( !$this->hasPrivilege($privilege) )
155
    {
156
      throw new BuildException(
157
        "Required DB privelege '{$privilege}' not granted for '{$this->_user}'@'{$this->_host}' on db '{$this->_dbName}'");
158
    }
159
  }
160
161
  protected function checkEngine($engine)
162
  {
163
    $q = $this->pdo->query('SHOW ENGINES;');
164
    $q->execute();
165
    foreach($q as $row)
166
    {
167
      if( $row['Engine'] == $engine and ($row['Support'] == 'YES' or $row['Support'] == 'DEFAULT') )
168
        return true;
169
    }
170
    throw new BuildException("Required Engine '$engine' is not supported by current DB driver");
171
  }
172
173
  protected function hasPrivilege($privilege)
174
  {
175
    return $this->_privilegeChecker->hasPrivilege($privilege, $this->_dbName, $this->_user, $this->_host);
176
  }
177
178
  private function connect()
179
  {
180
    $dsn = $dsn = $this->project->getProperty('db.driver').':'.'host='.$this->project->getProperty('db.host');
181
182
    try
183
    {
184
      $this->pdo = new PDO($dsn,
185
        $this->project->getProperty('db.username'),
186
        $this->project->getProperty('db.password'));
187
    }
188
    catch(PDOException $e)
189
    {
190
      throw new BuildException("CheckDbPermissionsTask: Could not connect to PDO: $dsn");
191
    }
192
193
    $this->_connected = true;
194
    $this->_user = $this->project->getProperty('db.mysqlUser');
195
    $this->_host = $this->project->getProperty('db.mysqlHost');
196
    $this->_dbName = $this->project->getProperty('db.dbname');
197
  }
198
}
199
200
201
/**
202
 * Привилегии.
203
 */
204
class PrivilegeEnum
205
{
206
  const TRIGGER = 'trigger';
207
  const SHOW_VIEW = 'show view';
208
  const CREATE_VIEW = 'create view';
209
  const CREATE_ROUTINE = 'create routine';
210
  const ALTER_ROUTINE = 'alter routine';
211
  const LOCK_TABLES = 'lock tables';
212
  const CREATE_TEMPORARY_TABLES = 'create temporary tables';
213
}
214
215
216
/**
217
 * Инкапсулиреут правила проверки привилегий.
218
 */
219
class PrivilegeChecker
220
{
221
  /**
222
   * Возвращает результат команды SHOW GRANTS;
223
   *
224
   * @param PDO $connection Соединение с базой данных.
225
   *
226
   * @throws BadMethodCallException
227
   * @return array Результат команды SHOW GRANTS;
228
   */
229
  public static function getShowGrantsOutput(PDO $connection)
230
  {
231
    if( !$query = $connection->query('SHOW GRANTS;') )
232
    {
233
      throw new BadMethodCallException($connection->errorInfo()[2], $connection->errorInfo()[1]);
234
    }
235
236
    return $query->fetchAll();
237
  }
238
239
  /**
240
   * @var string[] Массив GRANT команд.
241
   */
242
  private $_showGrantsOutput;
243
244
  /**
245
   * Создает новый объект для проверки привилегий в базе данных для пользователя.
246
   *
247
   * @param string[] $showGrantsRawOutput Результат команды SHOW GRANTS;
248
   */
249
  public function __construct(array $showGrantsRawOutput)
250
  {
251
    $this->_showGrantsOutput = $this->preprocess($showGrantsRawOutput);
0 ignored issues
show
Documentation introduced by
$showGrantsRawOutput is of type array<integer,string>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
252
  }
253
254
  /**
255
   * Проверает наличие указанной привилегии для определенного пользователя и хоста.
256
   *
257
   * @param string $privilege Название привилегии (см. PrivilegeEnum)
258
   * @param string $db Имя базы данных.
259
   * @param string $user Имя пользователя.
260
   * @param string $host Имя хоста.
261
   *
262
   * @return bool true в случае наличия привилегии, иначе false.
263
   */
264
  public function hasPrivilege($privilege, $db, $user, $host)
265
  {
266
    try
267
    {
268
      $grantQuery = $this->findRow($this->_showGrantsOutput, $db, $user, $host);
269
    }
270
    catch(UnexpectedValueException $e)
271
    {
272
      return false;
273
    }
274
275
    return $this->checkPrivilege($grantQuery, $privilege);
276
  }
277
278
  /**
279
   * Выполняет предварительную обработку для результата команды SHOW GRANTS;
280
   *
281
   * @param string $showGrantsRawOutput Результат команды SHOW GRANTS;
282
   *
283
   * @return string[] Массив GRANT команд.
284
   */
285
  private function preprocess($showGrantsRawOutput)
286
  {
287
    return array_map(function (array $rowAsArray)
288
    {
289
      return reset($rowAsArray);
290
    }, $showGrantsRawOutput);
291
  }
292
293
  /**
294
   * Отыскивает строку, содержащую GRANT команду, для указанного пользователя и хоста.
295
   *
296
   * @param string[] $grantCommands Все GRANT команды.
297
   * @param string $db Имя базы данных.
298
   * @param string $user Имя пользователя.
299
   * @param string $host Имя хоста.
300
   *
301
   * @throws UnexpectedValueException Бросается если GRANT команда для указанного пользователя и хоста не найдена.
302
   * @return string GRANT команда для указанного пользователя и хоста.
303
   */
304
  private function findRow(array $grantCommands, $db, $user, $host)
305
  {
306
    $candidates = array_filter($grantCommands, function ($row) use ($db, $user, $host)
307
    {
308
      /** @var $row string */
309
      if( stripos($row, 'GRANT USAGE ON') !== false )
310
      {
311
        return false;
312
      }
313
314
      return preg_match("/('{$user}'@'{$host}')|('{$user}'@'%')/", $row);
315
    });
316
317
    if( count($candidates) === 0 )
318
    {
319
      throw new UnexpectedValueException();
320
    }
321
322
    return reset($candidates);
323
  }
324
325
  private function parsePrivileges($string)
326
  {
327
    if( !preg_match('/GRANT\s+(?<privileges>.+)\s+ON/i', $string, $matches) )
328
      return array();
329
330
    $privilegeList = array_map(function ($privilege)
331
    {
332
      return strtolower(trim($privilege));
333
    }, explode(',', $matches['privileges']));
334
335
    return is_array($privilegeList) ? $privilegeList : array();
336
  }
337
338
  /**
339
   * Проверяет наличие привилегии в SQL GRANT команде.
340
   *
341
   * @param string $string Строка, содержащая SQL GRANT команду.
342
   * @param string $checkPrivilege Название привилегии на которую делается проверка.
343
   *
344
   * @return bool true в случае наличия привилегии, иначе false.
345
   */
346
  private function checkPrivilege($string, $checkPrivilege)
347
  {
348
    $privileges = $this->parsePrivileges($string);
349
350
    return in_array(strtolower($checkPrivilege), $privileges) || in_array('all privileges', $privileges) || in_array('all', $privileges);
351
  }
352
}