From cacdfc6e5069c56b9e5b4771c58244a74f83417e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 22 Sep 2022 09:30:03 +0200 Subject: [PATCH 1/5] Don't restrict the supported databases Signed-off-by: Joas Schilling --- appinfo/info.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index b807dcea..cd4b029d 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -22,8 +22,6 @@ - mysql - pgsql From 55bfb911d8d7a1b336d3c9cc104ec993959a251e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 22 Sep 2022 09:30:18 +0200 Subject: [PATCH 2/5] Bump Nextcloud requirements to match the PHP requirements Signed-off-by: Joas Schilling --- .github/workflows/test.yml | 9 +-------- appinfo/info.xml | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dfb3a721..3cdfaac4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,10 +12,6 @@ jobs: include: - php-version: '8.1' nextcloud-version: stable24 - - php-version: '8.0' - nextcloud-version: stable23 - - php-version: '8.0' - nextcloud-version: stable22 name: Nextcloud ${{ matrix.nextcloud-version }} php${{ matrix.php-version }} unit tests steps: - name: Set up php${{ matrix.php-version }} @@ -64,10 +60,7 @@ jobs: db: [ 'mysql' ] include: - php-versions: '8.0' - nextcloud-versions: stable23 - db: 'pgsql' - - php-versions: '8.0' - nextcloud-versions: stable22 + nextcloud-versions: master db: 'pgsql' name: Nextcloud${{ matrix.nextcloud-versions }}-${{ matrix.db }} smoke test services: diff --git a/appinfo/info.xml b/appinfo/info.xml index cd4b029d..0bf6c3f1 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -22,7 +22,7 @@ - + From 37966bb0ae4bea219fd5aeef51fb0edf00acbc1c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 22 Sep 2022 09:36:47 +0200 Subject: [PATCH 3/5] Use PHPUnit templates that also install the app Signed-off-by: Joas Schilling --- .github/workflows/phpunit-mysql.yml | 146 +++++++++++++++++++++++++++ .github/workflows/phpunit-pgsql.yml | 143 ++++++++++++++++++++++++++ .github/workflows/phpunit-sqlite.yml | 132 ++++++++++++++++++++++++ .github/workflows/test.yml | 32 ------ 4 files changed, 421 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/phpunit-mysql.yml create mode 100644 .github/workflows/phpunit-pgsql.yml create mode 100644 .github/workflows/phpunit-sqlite.yml diff --git a/.github/workflows/phpunit-mysql.yml b/.github/workflows/phpunit-mysql.yml new file mode 100644 index 00000000..17caf9cd --- /dev/null +++ b/.github/workflows/phpunit-mysql.yml @@ -0,0 +1,146 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +env: + # Location of the phpunit.xml and phpunit.integration.xml files + PHPUNIT_CONFIG: ./tests/phpunit.xml + PHPUNIT_INTEGRATION_CONFIG: ./tests/phpunit.integration.xml + +jobs: + phpunit-mysql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['7.4', '8.0', '8.1'] + server-versions: ['master'] + + services: + mysql: + image: mariadb:10.5 + ports: + - 4444:3306/tcp + env: + MYSQL_ROOT_PASSWORD: rootpassword + options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Enable ONLY_FULL_GROUP_BY MySQL option + run: | + echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword + echo "SELECT @@sql_mode;" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword + + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql + coverage: none + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up PHPUnit + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password + ./occ app:enable ${{ env.APP_NAME }} + + - name: Check PHPUnit config file existence + id: check_phpunit + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_CONFIG }} + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration config file existence + id: check_integration + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: ./vendor/phpunit/phpunit/phpunit -c ${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-mysql + + if: always() + + name: phpunit-mysql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-mysql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-pgsql.yml b/.github/workflows/phpunit-pgsql.yml new file mode 100644 index 00000000..e7dd034e --- /dev/null +++ b/.github/workflows/phpunit-pgsql.yml @@ -0,0 +1,143 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +env: + # Location of the phpunit.xml and phpunit.integration.xml files + PHPUNIT_CONFIG: ./tests/phpunit.xml + PHPUNIT_INTEGRATION_CONFIG: ./tests/phpunit.integration.xml + +jobs: + phpunit-pgsql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + services: + postgres: + image: postgres + ports: + - 4444:5432/tcp + env: + POSTGRES_USER: root + POSTGRES_PASSWORD: rootpassword + POSTGRES_DB: nextcloud + options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, pgsql, pdo_pgsql + coverage: none + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up PHPUnit + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password + ./occ app:enable ${{ env.APP_NAME }} + + - name: Check PHPUnit config file existence + id: check_phpunit + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_CONFIG }} + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration config file existence + id: check_integration + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: ./vendor/phpunit/phpunit/phpunit -c ${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-pgsql + + if: always() + + name: phpunit-pgsql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-sqlite.yml b/.github/workflows/phpunit-sqlite.yml new file mode 100644 index 00000000..4e606114 --- /dev/null +++ b/.github/workflows/phpunit-sqlite.yml @@ -0,0 +1,132 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +env: + # Location of the phpunit.xml and phpunit.integration.xml files + PHPUNIT_CONFIG: ./tests/phpunit.xml + PHPUNIT_INTEGRATION_CONFIG: ./tests/phpunit.integration.xml + +jobs: + phpunit-sqlite: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@v3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@v3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite + coverage: none + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/composer.json + + - name: Set up PHPUnit + # Only run if phpunit config file exists + if: steps.check_composer.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password + ./occ app:enable ${{ env.APP_NAME }} + + - name: Check PHPUnit config file existence + id: check_phpunit + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_CONFIG }} + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration config file existence + id: check_integration + uses: andstor/file-existence-action@v1 + with: + files: apps/${{ env.APP_NAME }}/${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outputs.files_exists == 'true' + working-directory: apps/${{ env.APP_NAME }} + run: ./vendor/phpunit/phpunit/phpunit -c ${{ env.PHPUNIT_INTEGRATION_CONFIG }} + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-sqlite + + if: always() + + name: phpunit-sqlite-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-sqlite.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3cdfaac4..fcf356d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,38 +3,6 @@ name: Test on: pull_request jobs: - unit-tests: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['8.1'] - nextcloud-version: ['master'] - include: - - php-version: '8.1' - nextcloud-version: stable24 - name: Nextcloud ${{ matrix.nextcloud-version }} php${{ matrix.php-version }} unit tests - steps: - - name: Set up php${{ matrix.php-version }} - uses: shivammathur/setup-php@master - with: - php-version: ${{ matrix.php-version }} - extensions: ctype,curl,dom,gd,iconv,intl,json,mbstring,openssl,posix,xml,zip - coverage: none - - name: Checkout Nextcloud - run: git clone https://github.com/nextcloud/server.git --recursive --depth 1 -b ${{ matrix.nextcloud-version }} nextcloud - - name: Install Nextcloud - run: php -f nextcloud/occ maintenance:install --database-name oc_autotest --database-user oc_autotest --admin-user admin --admin-pass admin --database sqlite --database-pass='' - - name: Checkout app - uses: actions/checkout@master - with: - path: nextcloud/apps/suspicious_login - - name: Install dependencies - working-directory: nextcloud/apps/suspicious_login - run: composer install - - name: Run tests - working-directory: nextcloud/apps/suspicious_login - run: composer run test:unit - frontend-unit-test: runs-on: ubuntu-latest name: Front-end unit tests From bd1bf9546a6289dbcbf8ca3bef5dacbb550860cc Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 22 Sep 2022 10:07:40 +0200 Subject: [PATCH 4/5] Rename table so the primary key is not too long Signed-off-by: Joas Schilling --- doc/stats.md | 8 +- lib/Db/LoginAddressAggregatedMapper.php | 2 +- lib/Migration/Version0Date20190115134303.php | 4 + .../Version4002Date20220922094803.php | 142 ++++++++++++++++++ .../Version4002Date20220922094804.php | 53 +++++++ lib/Service/ETLService.php | 6 +- 6 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 lib/Migration/Version4002Date20220922094803.php create mode 100644 lib/Migration/Version4002Date20220922094804.php diff --git a/doc/stats.md b/doc/stats.md index 4c75bc01..9e911c5e 100644 --- a/doc/stats.md +++ b/doc/stats.md @@ -33,13 +33,13 @@ ORDER BY year, ```sql SELECT (SELECT SUM(seen) - FROM oc_login_address_aggregated + FROM oc_login_ips_aggregated WHERE ip LIKE '%.%.%.%') / (SELECT SUM(seen) - FROM oc_login_address_aggregated) AS + FROM oc_login_ips_aggregated) AS pct_v4, (SELECT SUM(seen) - FROM oc_login_address_aggregated + FROM oc_login_ips_aggregated WHERE ip NOT LIKE '%.%.%.%') / (SELECT SUM(seen) - FROM oc_login_address_aggregated) AS + FROM oc_login_ips_aggregated) AS pct_v6 ``` diff --git a/lib/Db/LoginAddressAggregatedMapper.php b/lib/Db/LoginAddressAggregatedMapper.php index f5137512..1bcfb10f 100644 --- a/lib/Db/LoginAddressAggregatedMapper.php +++ b/lib/Db/LoginAddressAggregatedMapper.php @@ -29,7 +29,7 @@ class LoginAddressAggregatedMapper extends QBMapper { public function __construct(IDBConnection $db) { - parent::__construct($db, 'login_address_aggregated'); + parent::__construct($db, 'login_ips_aggregated'); } public function findAllIpV4() { diff --git a/lib/Migration/Version0Date20190115134303.php b/lib/Migration/Version0Date20190115134303.php index ae6649d6..8bef1552 100644 --- a/lib/Migration/Version0Date20190115134303.php +++ b/lib/Migration/Version0Date20190115134303.php @@ -43,6 +43,8 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt /** @var ISchemaWrapper $schema */ $schema = $schemaClosure(); + /** + * Replaced by Version4002Date20220922094803 for Oracle support $table = $schema->createTable('login_address_aggregated'); $table->addColumn('id', 'integer', [ 'autoincrement' => true, @@ -73,5 +75,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt $table->addUniqueIndex(['uid', 'ip']); return $schema; + */ + return null; } } diff --git a/lib/Migration/Version4002Date20220922094803.php b/lib/Migration/Version4002Date20220922094803.php new file mode 100644 index 00000000..6f14e36a --- /dev/null +++ b/lib/Migration/Version4002Date20220922094803.php @@ -0,0 +1,142 @@ + + * + * @author Joas Schilling + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\SuspiciousLogin\Migration; + +use Closure; +use OCP\DB\Exception; +use OCP\DB\ISchemaWrapper; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version4002Date20220922094803 extends SimpleMigrationStep { + /** + * @var IDBConnection + */ + protected $connection; + + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + } + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->createTable('login_ips_aggregated'); + $table->addColumn('id', 'integer', [ + 'autoincrement' => true, + 'notnull' => true, + 'length' => 4, + ]); + $table->addColumn('uid', 'string', [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('ip', 'string', [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('seen', 'integer', [ + 'notnull' => true, + 'length' => 4, + ]); + $table->addColumn('first_seen', 'integer', [ + 'notnull' => true, + 'length' => 4, + ]); + $table->addColumn('last_seen', 'integer', [ + 'notnull' => true, + 'length' => 4, + ]); + $table->setPrimaryKey(['id']); + $table->addUniqueIndex(['uid', 'ip']); + + return $schema; + } + + public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + if (!$schema->hasTable('login_address_aggregated')) { + return; + } + + $insert = $this->connection->getQueryBuilder(); + $insert->insert('login_ips_aggregated') + ->values([ + 'uid' => $insert->createParameter('uid'), + 'ip' => $insert->createParameter('ip'), + 'seen' => $insert->createParameter('seen'), + 'first_seen' => $insert->createParameter('first_seen'), + 'last_seen' => $insert->createParameter('last_seen'), + ]); + + $select = $this->connection->getQueryBuilder(); + $select->select('*') + ->from('login_address_aggregated') + ->where($select->expr()->gt('id', $select->createParameter('offset'))) + ->orderBy('id', 'ASC') + ->setMaxResults(1000); + + $offset = -1; + while ($offset !== 0) { + $offset = $this->chunkedCopying($insert, $select, max($offset, 0)); + } + } + + protected function chunkedCopying(IQueryBuilder $insert, IQueryBuilder $select, int $offset): int { + $select->setParameter('offset', $offset); + $newOffset = 0; + + $this->connection->beginTransaction(); + $result = $select->executeQuery(); + while ($row = $result->fetch()) { + $insert + ->setParameter('uid', $row['uid']) + ->setParameter('ip', $row['ip']) + ->setParameter('seen', (int) $row['seen'], IQueryBuilder::PARAM_INT) + ->setParameter('first_seen', (int) $row['first_seen'], IQueryBuilder::PARAM_INT) + ->setParameter('last_seen', (int) $row['last_seen'], IQueryBuilder::PARAM_INT) + ; + $insert->executeStatement(); + + $newOffset = (int) $row['id']; + } + $result->closeCursor(); + $this->connection->commit(); + + return $newOffset; + } +} diff --git a/lib/Migration/Version4002Date20220922094804.php b/lib/Migration/Version4002Date20220922094804.php new file mode 100644 index 00000000..ff982eb5 --- /dev/null +++ b/lib/Migration/Version4002Date20220922094804.php @@ -0,0 +1,53 @@ + + * + * @author 2018 Christoph Wurst + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\SuspiciousLogin\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; + +class Version4002Date20220922094804 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if ($schema->hasTable('login_address_aggregated')) { + $schema->dropTable('login_address_aggregated'); + return $schema; + } + + return null; + } +} diff --git a/lib/Service/ETLService.php b/lib/Service/ETLService.php index 4eb668dc..b49737db 100644 --- a/lib/Service/ETLService.php +++ b/lib/Service/ETLService.php @@ -90,7 +90,7 @@ public function extractAndTransform(int $max = self::MAX_BATCH_SIZE, OutputInter $insert = $this->db->getQueryBuilder(); $insert - ->insert('login_address_aggregated') + ->insert('login_ips_aggregated') ->values([ 'uid' => $insert->createParameter('uid'), 'ip' => $insert->createParameter('ip'), @@ -101,12 +101,12 @@ public function extractAndTransform(int $max = self::MAX_BATCH_SIZE, OutputInter $select = $this->db->getQueryBuilder(); $select ->select('seen', 'first_seen', 'last_seen') - ->from('login_address_aggregated') + ->from('login_ips_aggregated') ->where($select->expr()->eq('uid', $select->createParameter('uid'))) ->andWhere($select->expr()->eq('ip', $select->createParameter('ip'))); $update = $this->db->getQueryBuilder(); $update - ->update('login_address_aggregated') + ->update('login_ips_aggregated') ->set('seen', $update->createParameter('seen')) ->set('first_seen', $update->createParameter('first_seen')) ->set('last_seen', $update->createParameter('last_seen')) From 4e08f46c2e4c620c31a596a4b186527dbebe8aff Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 22 Sep 2022 10:12:32 +0200 Subject: [PATCH 5/5] Fix PHP CS Signed-off-by: Joas Schilling --- lib/Migration/Version0Date20190115134303.php | 60 +++++++++---------- .../Version4002Date20220922094803.php | 1 - 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/lib/Migration/Version0Date20190115134303.php b/lib/Migration/Version0Date20190115134303.php index 8bef1552..31baa1a3 100644 --- a/lib/Migration/Version0Date20190115134303.php +++ b/lib/Migration/Version0Date20190115134303.php @@ -45,36 +45,36 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt /** * Replaced by Version4002Date20220922094803 for Oracle support - $table = $schema->createTable('login_address_aggregated'); - $table->addColumn('id', 'integer', [ - 'autoincrement' => true, - 'notnull' => true, - 'length' => 4, - ]); - $table->addColumn('uid', 'string', [ - 'notnull' => true, - 'length' => 64, - ]); - $table->addColumn('ip', 'string', [ - 'notnull' => true, - 'length' => 64, - ]); - $table->addColumn('seen', 'integer', [ - 'notnull' => true, - 'length' => 4, - ]); - $table->addColumn('first_seen', 'integer', [ - 'notnull' => true, - 'length' => 4, - ]); - $table->addColumn('last_seen', 'integer', [ - 'notnull' => true, - 'length' => 4, - ]); - $table->setPrimaryKey(['id']); - $table->addUniqueIndex(['uid', 'ip']); - - return $schema; + * $table = $schema->createTable('login_address_aggregated'); + * $table->addColumn('id', 'integer', [ + * 'autoincrement' => true, + * 'notnull' => true, + * 'length' => 4, + * ]); + * $table->addColumn('uid', 'string', [ + * 'notnull' => true, + * 'length' => 64, + * ]); + * $table->addColumn('ip', 'string', [ + * 'notnull' => true, + * 'length' => 64, + * ]); + * $table->addColumn('seen', 'integer', [ + * 'notnull' => true, + * 'length' => 4, + * ]); + * $table->addColumn('first_seen', 'integer', [ + * 'notnull' => true, + * 'length' => 4, + * ]); + * $table->addColumn('last_seen', 'integer', [ + * 'notnull' => true, + * 'length' => 4, + * ]); + * $table->setPrimaryKey(['id']); + * $table->addUniqueIndex(['uid', 'ip']); + * + * return $schema; */ return null; } diff --git a/lib/Migration/Version4002Date20220922094803.php b/lib/Migration/Version4002Date20220922094803.php index 6f14e36a..c87fe4ae 100644 --- a/lib/Migration/Version4002Date20220922094803.php +++ b/lib/Migration/Version4002Date20220922094803.php @@ -26,7 +26,6 @@ namespace OCA\SuspiciousLogin\Migration; use Closure; -use OCP\DB\Exception; use OCP\DB\ISchemaWrapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection;