*/ class RdsRequestLogStorage extends AbstractRequestLogStorage implements RequestLogStorageReadable { const OPTION_PERSISTENCE = 'persistence_id'; const TABLE_NAME = 'request_log'; const COLUMN_USER_ID = RequestLogService::USER_ID; const COLUMN_USER_ROLES = RequestLogService::USER_ROLES; const COLUMN_ACTION = RequestLogService::ACTION; const COLUMN_EVENT_TIME = RequestLogService::EVENT_TIME; const COLUMN_DETAILS = RequestLogService::DETAILS; /** @var \Doctrine\DBAL\Connection */ private $connection; /** * @inheritdoc */ public function log(RequestInterface $request, User $user) { $data = $this->prepareData($request, $user); $this->getPersistence()->insert(self::TABLE_NAME, $data); } /** * @inheritdoc */ public function find(array $filters = [], array $options = []) { $queryBuilder = $this->getQueryBuilder(); $queryBuilder->select('*'); if (isset($options['limit'])) { $queryBuilder->setMaxResults(intval($options['limit'])); } if (isset($options['offset'])) { $queryBuilder->setFirstResult(intval($options['offset'])); } if (isset($options['group']) && in_array($options['group'], $this->getColumnNames())) { $queryBuilder->groupBy($options['group']); } foreach ($filters as $filter) { $this->addFilter($queryBuilder, $filter); } return new UserActivityLogIterator($this->getPersistence(), $queryBuilder); } /** * @inheritdoc */ public function count(array $filters = [], array $options = []) { $queryBuilder = $this->getQueryBuilder(); $queryBuilder->select('user_id'); foreach ($filters as $filter) { $this->addFilter($queryBuilder, $filter); } if (isset($options['group']) && in_array($options['group'], $this->getColumnNames())) { $queryBuilder->select($options['group']); $queryBuilder->groupBy($options['group']); } $stmt = $this->getPersistence()->query( 'SELECT count(*) as count FROM (' .$queryBuilder->getSQL() . ') as group_q', $queryBuilder->getParameters()); $data = $stmt->fetch(\PDO::FETCH_ASSOC); return intval($data['count']); } /** * @param QueryBuilder $queryBuilder * @param array $filter */ private function addFilter(QueryBuilder $queryBuilder, array $filter) { $colName = strtolower($filter[0]); $operation = strtolower($filter[1]); $val = $filter[2]; $val2 = isset($filter[3]) ? $filter[3] : null; if (!in_array($colName, $this->getColumnNames())) { return; } if (!in_array($operation, ['<', '>', '<>', '<=', '>=', '=', 'between', 'like'])) { return; } $params = []; if ($operation === 'between') { $condition = "r.$colName between ? AND ?"; $params[] = $val; $params[] = $val2; } else { $condition = "r.$colName $operation ?"; $params[] = $val; } $queryBuilder->andWhere($condition); $params = array_merge($queryBuilder->getParameters(), $params); $queryBuilder->setParameters($params); } /** * @return array */ private function getColumnNames() { return [ self::COLUMN_USER_ID, self::COLUMN_USER_ROLES, self::COLUMN_ACTION, self::COLUMN_EVENT_TIME, self::COLUMN_DETAILS, ]; } /** * @return \common_persistence_SqlPersistence */ private function getPersistence() { $persistenceManager = $this->getServiceManager()->get(\common_persistence_Manager::SERVICE_ID); return $persistenceManager->getPersistenceById($this->getOption(self::OPTION_PERSISTENCE)); } /** * @return \Doctrine\DBAL\Query\QueryBuilder */ private function getQueryBuilder() { if ($this->connection === null) { $this->connection = \Doctrine\DBAL\DriverManager::getConnection( $this->getPersistence()->getDriver()->getParams(), new \Doctrine\DBAL\Configuration() ); } return $this->connection->createQueryBuilder()->from(self::TABLE_NAME, 'r'); } /** * Initialize RDS Request log storage * * @param string $persistenceId * @return \common_report_Report */ public static function install($persistenceId = 'default') { $persistence = \common_persistence_Manager::getPersistence($persistenceId); $schemaManager = $persistence->getDriver()->getSchemaManager(); $schema = $schemaManager->createSchema(); $fromSchema = clone $schema; try { $table = $schema->createTable(self::TABLE_NAME); $table->addOption('engine', 'InnoDB'); $table->addColumn(static::COLUMN_USER_ID, "string", ["length" => 255]); $table->addColumn(static::COLUMN_USER_ROLES, "string", ["notnull" => true, "length" => 4096]); $table->addColumn(static::COLUMN_ACTION, "string", ["notnull" => false, "length" => 4096]); $table->addColumn(static::COLUMN_EVENT_TIME, 'decimal', ['precision' => 14, 'scale'=>4, "notnull" => true]); $table->addColumn(static::COLUMN_DETAILS, "text", ["notnull" => false]); $table->addIndex([static::COLUMN_USER_ID], 'IDX_' . static::TABLE_NAME . '_' . static::COLUMN_USER_ID); $table->addIndex([static::COLUMN_EVENT_TIME], 'IDX_' . static::TABLE_NAME . '_' . static::COLUMN_EVENT_TIME); } catch(SchemaException $e) { \common_Logger::i('Database Schema already up to date.'); } $queries = $persistence->getPlatform()->getMigrateSchemaSql($fromSchema, $schema); foreach ($queries as $query) { $persistence->exec($query); } return new \common_report_Report(\common_report_Report::TYPE_SUCCESS, __('User activity log successfully registered.')); } }