diff --git a/.github/workflows/ab-testing.yml b/.github/workflows/ab-testing.yml index a793dde..823054e 100644 --- a/.github/workflows/ab-testing.yml +++ b/.github/workflows/ab-testing.yml @@ -25,35 +25,37 @@ jobs: - name: Download Plugin uses: actions/checkout@master with: - path: app/Plugin/TwoFactorAuthCustomer42 - - name: Download Plugin TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomer44 + - name: Download Plugin TwoFactorAuthCustomerApp44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 - path: app/Plugin/TwoFactorAuthCustomerApp42 - - name: Download Plugin TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerApp44 + - name: Download Plugin TwoFactorAuthCustomerSms44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 - path: app/Plugin/TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerSms44 - name: Sleep for MySQL run: sleep 120s shell: bash - name: Install Plugin run: | - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms44 - name: Wait 30s for the database to load, (as I do not know the databases active state) run: sleep 30s - name: Start Load EC-CUBE @@ -220,17 +222,19 @@ jobs: - name: Download Plugin uses: actions/checkout@master with: - path: app/Plugin/TwoFactorAuthCustomer42 - - name: Download Plugin TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomer44 + - name: Download Plugin TwoFactorAuthCustomerApp44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 - path: app/Plugin/TwoFactorAuthCustomerApp42 - - name: Download Plugin TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerApp44 + - name: Download Plugin TwoFactorAuthCustomerSms44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 - path: app/Plugin/TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerSms44 - name: Start Load EC-CUBE run: | sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml @@ -240,19 +244,19 @@ jobs: shell: bash - name: Install Plugin run: | - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms44 - name: Wait for 30 seconds for the database to load, (because MySQL is slow to initialize) run: sleep 30s shell: bash @@ -438,17 +442,19 @@ jobs: - name: Download Plugin uses: actions/checkout@master with: - path: app/Plugin/TwoFactorAuthCustomer42 - - name: Download Plugin TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomer44 + - name: Download Plugin TwoFactorAuthCustomerApp44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 - path: app/Plugin/TwoFactorAuthCustomerApp42 - - name: Download Plugin TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerApp44 + - name: Download Plugin TwoFactorAuthCustomerSms44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 - path: app/Plugin/TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerSms44 - name: Start Load EC-CUBE run: | sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml @@ -458,19 +464,19 @@ jobs: shell: bash - name: Install Plugin run: | - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms44 - name: Request home page - PGSQL PLUGIN 10000 PRODUCTS run: | sudo apt-get install apache2-utils @@ -678,17 +684,19 @@ jobs: - name: Download Plugin uses: actions/checkout@master with: - path: app/Plugin/TwoFactorAuthCustomer42 - - name: Download Plugin TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomer44 + - name: Download Plugin TwoFactorAuthCustomerApp44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 - path: app/Plugin/TwoFactorAuthCustomerApp42 - - name: Download Plugin TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerApp44 + - name: Download Plugin TwoFactorAuthCustomerSms44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 - path: app/Plugin/TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerSms44 - name: Start Load EC-CUBE run: | sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml @@ -736,19 +744,19 @@ jobs: docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs ec-cube - name: Install Plugin run: | - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms44 docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console cache:clear - docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml exec -T ec-cube bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms44 - name: Restart Load EC-CUBE to wait for MySQL run: | docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml up -d diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index d57a645..b2dd4d3 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -71,39 +71,41 @@ jobs: bin/console doctrine:database:create --env=dev bin/console doctrine:schema:create --env=dev bin/console eccube:fixtures:load --env=dev - - name: Download Plugin TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomer44 uses: actions/checkout@master with: - path: app/Plugin/TwoFactorAuthCustomer42 - - name: Download Plugin TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomer44 + - name: Download Plugin TwoFactorAuthCustomerApp44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 - path: app/Plugin/TwoFactorAuthCustomerApp42 - - name: Download Plugin TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerApp44 + - name: Download Plugin TwoFactorAuthCustomerSms44 uses: actions/checkout@master with: repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 - path: app/Plugin/TwoFactorAuthCustomerSms42 + ref: '4.4' + path: app/Plugin/TwoFactorAuthCustomerSms44 - name: Install Plugins env: APP_ENV: ${{ matrix.app_env }} DATABASE_URL: ${{ matrix.database_url }} DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} run: | - bin/console eccube:plugin:install --code=TwoFactorAuthCustomer42 + bin/console eccube:plugin:install --code=TwoFactorAuthCustomer44 bin/console cache:clear - bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer44 bin/console cache:clear - bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp44 bin/console cache:clear - bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp44 bin/console cache:clear - bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms44 bin/console cache:clear - bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms44 - name: setup-chromedriver uses: nanasess/setup-chromedriver@master diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4227cd3..d2d45e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: CI for TwoFactorAuthCustomer42 +name: CI for TwoFactorAuthCustomer44 on: push: branches: @@ -17,19 +17,15 @@ on: jobs: run-on-linux: name: Run on Linux - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: - eccube_version: [ '4.2','4.3' ] - php: [ '7.4', '8.0', '8.1','8.2', '8.3' ] - db: [ 'mysql', 'mysql8', 'pgsql' ] - plugin_code: [ 'TwoFactorAuthCustomer42' ] + eccube_version: [ '4.4' ] + php: [ '8.2', '8.3', '8.4', '8.5' ] + db: [ 'mysql8', 'pgsql' ] + plugin_code: [ 'TwoFactorAuthCustomer44' ] include: - - db: mysql - database_url: mysql://root:password@127.0.0.1:3306/eccube_db - database_server_version: 5.7 - database_charset: utf8mb4 - db: mysql8 database_url: mysql://root:password@127.0.0.1:3308/eccube_db database_server_version: 8 @@ -38,24 +34,7 @@ jobs: database_url: postgres://postgres:password@127.0.0.1:5432/eccube_db database_server_version: 14 database_charset: utf8 - exclude: - - eccube_version: 4.2 - php: 8.2 - - eccube_version: 4.2 - php: 8.3 - - eccube_version: 4.3 - php: 7.4 - - eccube_version: 4.3 - php: 8.0 services: - mysql: - image: mysql:5.7 - env: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: ${{ matrix.dbname }} - ports: - - 3306:3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 mysql8: image: mysql:8 env: @@ -81,7 +60,7 @@ jobs: - 1025:1025 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup PHP uses: nanasess/setup-php@master @@ -93,17 +72,8 @@ jobs: PLUGIN_CODE: ${{ matrix.plugin_code }} run: | tar cvzf ${GITHUB_WORKSPACE}/${PLUGIN_CODE}.tar.gz ./* - - - name: Setup mock-package-api - env: - PLUGIN_CODE: ${{ matrix.plugin_code }} - run: | - mkdir -p /tmp/repos - cp ${GITHUB_WORKSPACE}/${PLUGIN_CODE}.tar.gz /tmp/repos/${PLUGIN_CODE}.tgz - docker run --name package-api -d -v /tmp/repos:/repos -e MOCK_REPO_DIR=/repos -p 8080:8080 eccube/mock-package-api:composer2 - - name: Checkout EC-CUBE - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: 'EC-CUBE/ec-cube' ref: ${{ matrix.eccube_version }} @@ -112,8 +82,8 @@ jobs: - name: Get Composer Cache Directory id: composer-cache run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" - - uses: actions/cache@v1 + echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + - uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -121,7 +91,9 @@ jobs: ${{ runner.os }}-composer- - name: Install to composer working-directory: 'ec-cube' - run: composer install --no-interaction -o --apcu-autoloader + # Symfony 7.4 の symfony/cache が ext-redis <6.1 と衝突するが、ランナーには + # 古い php-redis(5.3.7) が入っている。本プラグイン/本体テストは redis 未使用のため無視する。 + run: composer install --no-interaction -o --apcu-autoloader --ignore-platform-req=ext-redis - name: Setup EC-CUBE env: @@ -130,7 +102,6 @@ jobs: DATABASE_URL: ${{ matrix.database_url }} DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} DATABASE_CHARSET: ${{ matrix.database_charset }} - ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' working-directory: 'ec-cube' run: | bin/console doctrine:database:create @@ -144,12 +115,28 @@ jobs: DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} DATABASE_CHARSET: ${{ matrix.database_charset }} PLUGIN_CODE: ${{ matrix.plugin_code }} - ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' working-directory: 'ec-cube' run: | - bin/console eccube:composer:require ec-cube/twofactorauthcustomer42 - bin/console cache:clear --no-warmup + bin/console eccube:plugin:install --code=${PLUGIN_CODE} --path=${GITHUB_WORKSPACE}/${PLUGIN_CODE}.tar.gz bin/console eccube:plugin:enable --code=${PLUGIN_CODE} + bin/console cache:clear --no-warmup + - name: Run PHPUnit + env: + APP_ENV: 'test' + APP_DEBUG: 0 + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + DATABASE_CHARSET: ${{ matrix.database_charset }} + PLUGIN_CODE: ${{ matrix.plugin_code }} + working-directory: 'ec-cube' + run: | + # 有効化したプラグインのルーティングはコンテナのコンパイル時に確定する。 + # phpunit プロセスでの遅延コンパイルに任せると DB/タイミングで有効プラグイン一覧を + # 取りこぼし RouteNotFound になることがあるため、クリーンなプロセスで warmup して確定させる。 + bin/console cache:clear --no-warmup + bin/console cache:warmup + ./vendor/bin/phpunit -c app/Plugin/${PLUGIN_CODE}/phpunit.xml.dist app/Plugin/${PLUGIN_CODE}/Tests + - name: Disable Plugin working-directory: 'ec-cube' env: @@ -159,7 +146,6 @@ jobs: DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} DATABASE_CHARSET: ${{ matrix.database_charset }} PLUGIN_CODE: ${{ matrix.plugin_code }} - ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' run: bin/console eccube:plugin:disable --code=${PLUGIN_CODE} - name: Uninstall Plugin @@ -170,6 +156,83 @@ jobs: DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} DATABASE_CHARSET: ${{ matrix.database_charset }} PLUGIN_CODE: ${{ matrix.plugin_code }} - ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' working-directory: 'ec-cube' run: bin/console eccube:plugin:uninstall --code=${PLUGIN_CODE} + + static-analysis: + name: Static Analysis + runs-on: ubuntu-24.04 + # 静的解析は DB 種別に依存しないため、SQLite 1 構成で一度だけ実行する。 + # (php-cs-fixer / rector は DB 不要だが、phpstan は objectManagerLoader が + # カーネルを起動し EccubeExtension が dtb_plugin を読むため本体+DBが必要) + env: + PLUGIN_CODE: TwoFactorAuthCustomer44 + APP_ENV: 'test' + APP_DEBUG: 0 + DATABASE_URL: 'sqlite:///var/eccube.db' + DATABASE_SERVER_VERSION: 3 + DATABASE_CHARSET: 'utf8' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: nanasess/setup-php@master + with: + php-version: '8.5' + + - name: Archive Plugin + run: | + tar cvzf ${GITHUB_WORKSPACE}/${PLUGIN_CODE}.tar.gz ./* + - name: Checkout EC-CUBE + uses: actions/checkout@v4 + with: + repository: 'EC-CUBE/ec-cube' + ref: '4.4' + path: 'ec-cube' + + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + - uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + - name: Install to composer + working-directory: 'ec-cube' + run: composer install --no-interaction -o --apcu-autoloader --ignore-platform-req=ext-redis + + - name: Setup EC-CUBE + working-directory: 'ec-cube' + run: | + # DBAL 4 の SQLite は doctrine:database:create 非対応(getCreateDatabaseSQL が削除済み)。 + # 本体 InstallerCommand と同様、SQLite ではファイル作成をスキップし schema:create で用意する。 + if [[ "${DATABASE_URL}" != sqlite* ]]; then + bin/console doctrine:database:create + fi + bin/console doctrine:schema:create + # プラグイン有効化時に DeviceType 等のマスタデータを参照するため fixtures を投入する + bin/console eccube:fixtures:load + - name: Setup Plugin + working-directory: 'ec-cube' + run: | + bin/console eccube:plugin:install --code=${PLUGIN_CODE} --path=${GITHUB_WORKSPACE}/${PLUGIN_CODE}.tar.gz + bin/console eccube:plugin:enable --code=${PLUGIN_CODE} + bin/console cache:clear --no-warmup + + - name: Run php-cs-fixer + working-directory: 'ec-cube' + run: ./vendor/bin/php-cs-fixer fix --config=app/Plugin/${PLUGIN_CODE}/Resource/.php-cs-fixer.dist.php --dry-run --diff + + - name: Run Rector + working-directory: 'ec-cube' + run: ./vendor/bin/rector process --config=app/Plugin/${PLUGIN_CODE}/Resource/rector.php --dry-run + + - name: Run PHPStan + working-directory: 'ec-cube' + run: | + bin/console cache:clear --no-warmup + ./vendor/bin/phpstan analyse -c app/Plugin/${PLUGIN_CODE}/phpstan.neon.dist --no-progress diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a4b67a..6319ea0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,19 +8,23 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Packaging working-directory: ../ run: | rm -rf $GITHUB_WORKSPACE/.github + # 開発・テスト用ファイルは配布パッケージに含めない + rm -rf $GITHUB_WORKSPACE/docker-compose*.yml $GITHUB_WORKSPACE/dockerbuild rm -rf $GITHUB_WORKSPACE/doc + rm -f $GITHUB_WORKSPACE/CLAUDE.md $GITHUB_WORKSPACE/phpstan.neon.dist + rm -f $GITHUB_WORKSPACE/Resource/rector.php "$GITHUB_WORKSPACE/Resource/.php-cs-fixer.dist.php" find $GITHUB_WORKSPACE -name "dummy" -delete find $GITHUB_WORKSPACE -name ".git*" -and ! -name ".gitkeep" -print0 | xargs -0 rm -rf chmod -R o+w $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE tar cvzf ../${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz ./* - name: Upload binaries to release of TGZ - uses: svenstaro/upload-release-action@v2 + uses: svenstaro/upload-release-action@v1-release with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: ${{ runner.workspace }}/${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz diff --git a/Controller/Admin/ConfigController.php b/Controller/Admin/ConfigController.php index 37a266f..e784a6d 100644 --- a/Controller/Admin/ConfigController.php +++ b/Controller/Admin/ConfigController.php @@ -5,48 +5,42 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Controller\Admin; +namespace Plugin\TwoFactorAuthCustomer44\Controller\Admin; use Eccube\Controller\AbstractController; -use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthConfigType; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Plugin\TwoFactorAuthCustomer44\Form\Type\TwoFactorAuthConfigType; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthConfigRepository; +use Symfony\Bridge\Twig\Attribute\Template; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; /** - * Class SmsController + * Class ConfigController */ class ConfigController extends AbstractController { - /** - * @var TwoFactorAuthConfigRepository - */ - private $smsConfigRepository; - /** * ConfigController constructor. */ - public function __construct(TwoFactorAuthConfigRepository $smsConfigRepository) - { - $this->smsConfigRepository = $smsConfigRepository; + public function __construct( + private readonly TwoFactorAuthConfigRepository $smsConfigRepository, + ) { } /** - * @Route("/%eccube_admin_route%/two_factor_auth_customer42/config", name="two_factor_auth_customer42_admin_config", methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/admin/config.twig") - * * @param Request $request * - * @return RedirectResponse|array + * @return RedirectResponse|array */ + #[Route(path: '/%eccube_admin_route%/two_factor_auth_customer44/config', name: 'two_factor_auth_customer44_admin_config', methods: ['GET', 'POST'])] + #[Template('@TwoFactorAuthCustomer44/admin/config.twig')] public function index(Request $request) { // 設定情報、フォーム情報を取得 @@ -72,14 +66,14 @@ public function index(Request $request) // フォームの入力データを保存 $this->entityManager->persist($SmsConfig); - $this->entityManager->flush($SmsConfig); + $this->entityManager->flush(); // 完了メッセージを表示 log_info('config', ['status' => 'Success']); $this->addSuccess('プラグインの設定を保存しました。', 'admin'); // 設定画面にリダイレクト - return $this->redirectToRoute('two_factor_auth_customer42_admin_config'); + return $this->redirectToRoute('two_factor_auth_customer44_admin_config'); } return [ diff --git a/Controller/CustomerPersonalValidationController.php b/Controller/CustomerPersonalValidationController.php index ec43123..76a12a1 100644 --- a/Controller/CustomerPersonalValidationController.php +++ b/Controller/CustomerPersonalValidationController.php @@ -5,83 +5,57 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Controller; +namespace Plugin\TwoFactorAuthCustomer44\Controller; -use Eccube\Common\Constant; use Eccube\Controller\AbstractController; use Eccube\Entity\Customer; use Eccube\Repository\CustomerRepository; -use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthPhoneNumberTypeCustomer; -use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthSmsTypeCustomer; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Plugin\TwoFactorAuthCustomer44\Form\Type\TwoFactorAuthPhoneNumberTypeCustomer; +use Plugin\TwoFactorAuthCustomer44\Form\Type\TwoFactorAuthSmsTypeCustomer; +use Plugin\TwoFactorAuthCustomer44\Service\CustomerTwoFactorAuthService; +use Symfony\Bridge\Twig\Attribute\Template; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; use Symfony\Component\RateLimiter\RateLimiterFactory; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Twig\Environment; -use Twig\Error\LoaderError; -use Twig\Error\RuntimeError; -use Twig\Error\SyntaxError; -use Twilio\Exceptions\ConfigurationException; -use Twilio\Exceptions\TwilioException; use Twilio\Rest\Api\V2010\Account\MessageInstance; class CustomerPersonalValidationController extends AbstractController { - /** - * @var CustomerRepository - */ - protected CustomerRepository $customerRepository; - - /** - * @var CustomerTwoFactorAuthService - */ - protected CustomerTwoFactorAuthService $customerTwoFactorAuthService; - - /** - * @var Environment - */ - protected Environment $twig; - private RateLimiterFactory $deviceAuthRequestEmailLimiter; - /** * TwoFactorAuthCustomerController constructor. * - * @param CustomerRepository $customerRepository , - * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService , + * @param RateLimiterFactory $deviceAuthRequestEmailLimiter + * @param CustomerRepository $customerRepository + * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService * @param Environment $twig */ public function __construct( - RateLimiterFactory $deviceAuthRequestEmailLimiter, - CustomerRepository $customerRepository, - CustomerTwoFactorAuthService $customerTwoFactorAuthService, - Environment $twig + private readonly RateLimiterFactory $deviceAuthRequestEmailLimiter, + protected CustomerRepository $customerRepository, + protected CustomerTwoFactorAuthService $customerTwoFactorAuthService, + protected Environment $twig, ) { - $this->customerRepository = $customerRepository; - $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->twig = $twig; - $this->deviceAuthRequestEmailLimiter = $deviceAuthRequestEmailLimiter; } /** * (デバイス認証時)デバイス認証ワンタイムトークン入力画面. * - * @Route("/two_factor_auth/device_auth/input_onetime/{secret_key}", name="plg_customer_2fa_device_auth_input_onetime", requirements={"secret_key" = "^[a-zA-Z0-9]+$"}, methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/default/device_auth/input.twig") - * * @param Request $request - * @param $secret_key + * @param string $secret_key * - * @return array|RedirectResponse + * @return array|RedirectResponse */ + #[Route(path: '/two_factor_auth/device_auth/input_onetime/{secret_key}', name: 'plg_customer_2fa_device_auth_input_onetime', requirements: ['secret_key' => '^[a-zA-Z0-9]+$'], methods: ['GET', 'POST'])] + #[Template('@TwoFactorAuthCustomer44/default/device_auth/input.twig')] public function deviceAuthInputOneTime(Request $request, $secret_key) { if ($this->isGranted('ROLE_USER')) { @@ -90,7 +64,6 @@ public function deviceAuthInputOneTime(Request $request, $secret_key) } $error = null; - /** @var Customer $Customer */ $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); if ($Customer === null) { @@ -133,11 +106,10 @@ public function deviceAuthInputOneTime(Request $request, $secret_key) 'entry_activate', ['secret_key' => $secret_key] ); - } else { - // 認証済の場合はスキップ - log_warning('[デバイス認証(SMS)] 既に認証済みの電話番号指定'); - $error = trans('front.2fa.onetime.invalid_message__reinput'); } + // 認証済の場合はスキップ + log_warning('[デバイス認証(SMS)] 既に認証済みの電話番号指定'); + $error = trans('front.2fa.onetime.invalid_message__reinput'); } } else { $error = trans('front.2fa.onetime.invalid_message__reinput'); @@ -155,20 +127,13 @@ public function deviceAuthInputOneTime(Request $request, $secret_key) /** * (デバイス認証時)デバイス認証 送信先入力画面. * - * @Route("/two_factor_auth/device_auth/send_onetime/{secret_key}", name="plg_customer_2fa_device_auth_send_onetime", requirements={"secret_key" = "^[a-zA-Z0-9]+$"}, methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/default/device_auth/send.twig") - * * @param Request $request - * @param $secret_key + * @param string $secret_key * - * @return array|RedirectResponse - * - * @throws ConfigurationException - * @throws LoaderError - * @throws RuntimeError - * @throws SyntaxError - * @throws TwilioException + * @return array|RedirectResponse */ + #[Route(path: '/two_factor_auth/device_auth/send_onetime/{secret_key}', name: 'plg_customer_2fa_device_auth_send_onetime', requirements: ['secret_key' => '^[a-zA-Z0-9]+$'], methods: ['GET', 'POST'])] + #[Template('@TwoFactorAuthCustomer44/default/device_auth/send.twig')] public function deviceAuthSendOneTime(Request $request, $secret_key) { if ($this->isGranted('ROLE_USER')) { @@ -177,7 +142,6 @@ public function deviceAuthSendOneTime(Request $request, $secret_key) } $error = null; - /** @var Customer $Customer */ $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); if ($Customer === null) { throw $this->createNotFoundException(); @@ -212,9 +176,8 @@ public function deviceAuthSendOneTime(Request $request, $secret_key) 'plg_customer_2fa_device_auth_input_onetime', ['secret_key' => $secret_key] ); - } else { - $error = trans('front.2fa.sms.send.failure_message'); } + $error = trans('front.2fa.sms.send.failure_message'); } return [ @@ -228,12 +191,12 @@ public function deviceAuthSendOneTime(Request $request, $secret_key) /** * デバイス認証用のワンタイムトークンチェック. * - * @param $Customer - * @param $token + * @param Customer $Customer + * @param string $token * - * @return boolean + * @return bool */ - private function checkDeviceToken($Customer, $token): bool + private function checkDeviceToken(Customer $Customer, string $token): bool { $now = new \DateTime(); @@ -251,15 +214,8 @@ private function checkDeviceToken($Customer, $token): bool * @param string $phoneNumber * * @return MessageInstance - * - * @throws LoaderError - * @throws RuntimeError - * @throws SyntaxError - * @throws ConfigurationException - * @throws TwilioException - * @throws \Exception */ - private function sendDeviceToken(Customer $Customer, string $phoneNumber) + private function sendDeviceToken(Customer $Customer, string $phoneNumber): MessageInstance { // ワンタイムトークン生成・保存 $token = $this->customerTwoFactorAuthService->generateOneTimeTokenValue(); @@ -271,7 +227,7 @@ private function sendDeviceToken(Customer $Customer, string $phoneNumber) $this->entityManager->flush(); // ワンタイムトークン送信メッセージをレンダリング - $twig = 'TwoFactorAuthCustomer42/Resource/template/default/sms/onetime_message.twig'; + $twig = '@TwoFactorAuthCustomer44/default/sms/onetime_message.twig'; $body = $this->twig->render($twig, [ 'Customer' => $Customer, 'token' => $token, diff --git a/Controller/TwoFactorAuthCustomerController.php b/Controller/TwoFactorAuthCustomerController.php index 568b907..7ad9470 100644 --- a/Controller/TwoFactorAuthCustomerController.php +++ b/Controller/TwoFactorAuthCustomerController.php @@ -5,75 +5,65 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Controller; +namespace Plugin\TwoFactorAuthCustomer44\Controller; use Eccube\Controller\AbstractController; use Eccube\Entity\Customer; use Eccube\Repository\CustomerRepository; -use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthTypeCustomer; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Plugin\TwoFactorAuthCustomer44\Form\Type\TwoFactorAuthTypeCustomer; +use Plugin\TwoFactorAuthCustomer44\Service\CustomerTwoFactorAuthService; +use Symfony\Bridge\Twig\Attribute\Template; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Twig\Environment; class TwoFactorAuthCustomerController extends AbstractController { - /** - * @var CustomerRepository - */ - protected CustomerRepository $customerRepository; - - /** - * @var CustomerTwoFactorAuthService - */ - protected CustomerTwoFactorAuthService $customerTwoFactorAuthService; - /** - * @var Environment - */ - protected Environment $twig; - /** * TwoFactorAuthCustomerController constructor. * - * @param CustomerRepository $customerRepository , - * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService , + * @param CustomerRepository $customerRepository + * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService * @param Environment $twig */ public function __construct( - CustomerRepository $customerRepository, - CustomerTwoFactorAuthService $customerTwoFactorAuthService, - Environment $twig + protected CustomerRepository $customerRepository, + protected CustomerTwoFactorAuthService $customerTwoFactorAuthService, + protected Environment $twig, ) { - $this->customerRepository = $customerRepository; - $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->twig = $twig; } /** * (ログイン時)二段階認証設定(選択)画面. * - * @Route("/mypage/two_factor_auth/select_type", name="plg_customer_2fa_auth_type_select", methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/default/tfa/select_type.twig") + * @return array|RedirectResponse */ + #[Route(path: '/mypage/two_factor_auth/select_type', name: 'plg_customer_2fa_auth_type_select', methods: ['GET', 'POST'])] + #[Template('@TwoFactorAuthCustomer44/default/tfa/select_type.twig')] public function selectAuthType(Request $request) { if ($this->isTwoFactorAuthed()) { return $this->redirectToRoute($this->getCallbackRoute()); } - /** @var Customer $Customer */ $Customer = $this->getUser(); + if (!$Customer instanceof Customer) { + return $this->redirectToRoute('mypage'); + } // 2段階認証方式が選択されている場合は、その方式の初回認証画面へ遷移 - if ($Customer !== null && $Customer->getTwoFactorAuthType() !== null) { - return $this->redirectToRoute($Customer->getTwoFactorAuthType()->getRoute()); + if ($Customer->getTwoFactorAuthType() !== null) { + $route = $Customer->getTwoFactorAuthType()->getRoute(); + if ($route !== null) { + return $this->redirectToRoute($route); + } } $error = null; @@ -89,11 +79,11 @@ public function selectAuthType(Request $request) // 2段階認証を有効に更新 $this->entityManager->persist($Customer); $this->entityManager->flush(); + // 初回認証を実施 return $this->redirectToRoute($TwoFactorAuthType->getRoute()); - } else { - $error = trans('front.2fa.onetime.invalid_message__reinput'); } + $error = trans('front.2fa.onetime.invalid_message__reinput'); } return [ @@ -106,13 +96,12 @@ public function selectAuthType(Request $request) /** * 認証済みか否か. * - * @return boolean + * @return bool */ protected function isTwoFactorAuthed(): bool { - /** @var Customer $Customer */ $Customer = $this->getUser(); - if ($Customer != null && !$this->customerTwoFactorAuthService->isAuthed($Customer, $this->getCallbackRoute())) { + if ($Customer instanceof Customer && !$this->customerTwoFactorAuthService->isAuthed($Customer, $this->getCallbackRoute())) { return false; } diff --git a/Entity/BaseInfoTrait.php b/Entity/BaseInfoTrait.php index 0ceda8d..3ec45f9 100644 --- a/Entity/BaseInfoTrait.php +++ b/Entity/BaseInfoTrait.php @@ -5,66 +5,49 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Entity; +namespace Plugin\TwoFactorAuthCustomer44\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Eccube\Annotation\EntityExtension; +use Eccube\Attribute\EntityExtension; +use Eccube\Entity\BaseInfo; -/** - * @EntityExtension("Eccube\Entity\BaseInfo") - */ +#[EntityExtension(BaseInfo::class)] trait BaseInfoTrait { /** * 2段階認証機能の利用 - * - * @var bool - * - * @ORM\Column(name="two_factor_auth_use", type="boolean", nullable=false, options={"default":false}) */ - private bool $two_factor_auth_use; + #[ORM\Column(name: 'two_factor_auth_use', type: Types::BOOLEAN, nullable: false, options: ['default' => false])] + private bool $two_factor_auth_use = false; + /** * SMS通知の設定 - * - * @var bool - * - * @ORM\Column(name="option_activate_device", type="boolean", nullable=false, options={"default":false}) */ - private bool $option_activate_device; + #[ORM\Column(name: 'option_activate_device', type: Types::BOOLEAN, nullable: false, options: ['default' => false])] + private bool $option_activate_device = false; - /** - * @return bool - */ public function isTwoFactorAuthUse(): bool { return $this->two_factor_auth_use; } - /** - * @param bool $two_factor_auth_use - */ public function setTwoFactorAuthUse(bool $two_factor_auth_use): void { $this->two_factor_auth_use = $two_factor_auth_use; } - /** - * @return bool - */ public function isOptionActivateDevice(): bool { return $this->option_activate_device; } - /** - * @param bool $option_activate_device - */ public function setOptionActivateDevice(bool $option_activate_device): void { $this->option_activate_device = $option_activate_device; diff --git a/Entity/CustomerTrait.php b/Entity/CustomerTrait.php index 6359fc3..1a4af4e 100644 --- a/Entity/CustomerTrait.php +++ b/Entity/CustomerTrait.php @@ -5,88 +5,56 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Entity; +namespace Plugin\TwoFactorAuthCustomer44\Entity; use Doctrine\Common\Collections\Collection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Eccube\Annotation\EntityExtension; +use Eccube\Attribute\EntityExtension; +use Eccube\Entity\Customer; -/** - * @EntityExtension("Eccube\Entity\Customer") - */ +#[EntityExtension(Customer::class)] trait CustomerTrait { - /** - * @var ?string - * - * @ORM\Column(name="device_auth_one_time_token", type="string", length=255, nullable=true) - */ + #[ORM\Column(name: 'device_auth_one_time_token', type: Types::STRING, length: 255, nullable: true)] private ?string $device_auth_one_time_token = null; - /** - * @var \DateTime|null - * - * @ORM\Column(name="device_auth_one_time_token_expire", type="datetimetz", nullable=true) - */ - private $device_auth_one_time_token_expire; + #[ORM\Column(name: 'device_auth_one_time_token_expire', type: Types::DATETIMETZ_MUTABLE, nullable: true)] + private ?\DateTime $device_auth_one_time_token_expire = null; - /** - * @var boolean - * - * @ORM\Column(name="device_authed", type="boolean", nullable=false, options={"default":false}) - */ + #[ORM\Column(name: 'device_authed', type: Types::BOOLEAN, nullable: false, options: ['default' => false])] private bool $device_authed = false; - /** - * @var string|null - * - * @ORM\Column(name="device_authed_phone_number", type="string", length=14, nullable=true) - */ + #[ORM\Column(name: 'device_authed_phone_number', type: Types::STRING, length: 14, nullable: true)] private ?string $device_authed_phone_number = null; /** * 2段階認証機能の設定 - * - * @var int|null - * - * @ORM\Column(name="two_factor_auth_type", type="integer", nullable=true) */ + #[ORM\Column(name: 'two_factor_auth_type', type: Types::INTEGER, nullable: true)] private ?int $two_factor_auth_type = null; - /** - * @var TwoFactorAuthType - * - * @ORM\ManyToOne(targetEntity="\Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType") - * @ORM\JoinColumns({ - * @ORM\JoinColumn(name="two_factor_auth_type_id", referencedColumnName="id") - * }) - */ - private $TwoFactorAuthType = null; + #[ORM\ManyToOne(targetEntity: TwoFactorAuthType::class)] + #[ORM\JoinColumn(name: 'two_factor_auth_type_id', referencedColumnName: 'id')] + private ?TwoFactorAuthType $TwoFactorAuthType = null; /** - * @var Collection - * - * @ORM\OneToMany(targetEntity="\Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie", mappedBy="Customer") + * @var Collection|null */ + #[ORM\OneToMany(targetEntity: TwoFactorAuthCustomerCookie::class, mappedBy: 'Customer')] private $TwoFactorAuthCustomerCookies; - /** - * @return string - */ public function getDeviceAuthOneTimeToken(): ?string { return $this->device_auth_one_time_token; } - /** - * @param string|null $device_auth_one_time_token - */ public function setDeviceAuthOneTimeToken(?string $device_auth_one_time_token): void { $this->device_auth_one_time_token = $device_auth_one_time_token; @@ -94,10 +62,8 @@ public function setDeviceAuthOneTimeToken(?string $device_auth_one_time_token): /** * Get resetExpire. - * - * @return \DateTime|null */ - public function getDeviceAuthOneTimeTokenExpire() + public function getDeviceAuthOneTimeTokenExpire(): ?\DateTime { return $this->device_auth_one_time_token_expire; } @@ -105,55 +71,41 @@ public function getDeviceAuthOneTimeTokenExpire() /** * Set oneTimeTokenExpire. * - * @param \DateTime|null $resetExpire + * @param mixed $deviceAuthOneTimeTokenExpire * * @return Customer */ - public function setDeviceAuthOneTimeTokenExpire($deviceAuthOneTimeTokenExpire = null) + public function setDeviceAuthOneTimeTokenExpire(mixed $deviceAuthOneTimeTokenExpire = null): Customer { $this->device_auth_one_time_token_expire = $deviceAuthOneTimeTokenExpire; return $this; } - /** - * @return bool - */ public function isDeviceAuthed(): bool { return $this->device_authed; } - /** - * @param bool $device_authed - */ public function setDeviceAuthed(bool $device_authed): void { $this->device_authed = $device_authed; } - /** - * @return string - */ public function getDeviceAuthedPhoneNumber(): ?string { return $this->device_authed_phone_number; } - /** - * @param string|null $device_authed_phone_number - */ public function setDeviceAuthedPhoneNumber(?string $device_authed_phone_number): void { $this->device_authed_phone_number = $device_authed_phone_number; } /** - * Get sex. - * - * @return TwoFactorAuthType|null + * Get two-factor auth type. */ - public function getTwoFactorAuthType() + public function getTwoFactorAuthType(): ?TwoFactorAuthType { return $this->TwoFactorAuthType; } @@ -161,26 +113,20 @@ public function getTwoFactorAuthType() /** * Set two-factor auth type. * - * @param TwoFactorAuthType|null $twoFactorAuthType + * @return $this */ - public function setTwoFactorAuthType(TwoFactorAuthType $twoFactorAuthType = null) + public function setTwoFactorAuthType(?TwoFactorAuthType $twoFactorAuthType = null) { $this->TwoFactorAuthType = $twoFactorAuthType; return $this; } - /** - * @return Collection - */ public function getTwoFactorAuthCustomerCookies(): Collection { return $this->TwoFactorAuthCustomerCookies; } - /** - * @param Collection $TwoFactorAuthCustomerCookies - */ public function setTwoFactorAuthCustomerCookies(Collection $TwoFactorAuthCustomerCookies): void { $this->TwoFactorAuthCustomerCookies = $TwoFactorAuthCustomerCookies; diff --git a/Entity/TwoFactorAuthConfig.php b/Entity/TwoFactorAuthConfig.php index 94b9149..15c769f 100644 --- a/Entity/TwoFactorAuthConfig.php +++ b/Entity/TwoFactorAuthConfig.php @@ -5,69 +5,49 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Entity; +namespace Plugin\TwoFactorAuthCustomer44\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthConfigRepository; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; -use Symfony\Component\Validator\Constraints as Assert; /** * TwoFactorConfig - * - * @ORM\Table(name="plg_two_factor_auth_config") - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) - * @ORM\HasLifecycleCallbacks() - * @ORM\Entity(repositoryClass="Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository") - * @UniqueEntity("id") */ +#[ORM\Table(name: 'plg_two_factor_auth_config')] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'discriminator_type', type: Types::STRING, length: 255)] +#[ORM\HasLifecycleCallbacks] +#[ORM\Entity(repositoryClass: TwoFactorAuthConfigRepository::class)] +#[UniqueEntity('id')] class TwoFactorAuthConfig extends AbstractEntity { - /** - * @var int - * - * @ORM\Column(name="id", type="integer", options={"unsigned":true}) - * @ORM\Id - * @ORM\GeneratedValue(strategy="IDENTITY") - */ - private $id; + #[ORM\Column(name: 'id', type: Types::INTEGER, options: ['unsigned' => true])] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'IDENTITY')] + private ?int $id = null; - /** - * @var string - * - * @ORM\Column(name="api_key", type="string", nullable=true, length=200) - */ - private $api_key = null; + #[ORM\Column(name: 'api_key', type: Types::STRING, nullable: true, length: 200)] + private ?string $api_key = null; - /** - * @var string - * - * @ORM\Column(name="api_secret", type="string", nullable=true, length=200) - */ - private $api_secret = null; + #[ORM\Column(name: 'api_secret', type: Types::STRING, nullable: true, length: 200)] + private ?string $api_secret = null; - private $plain_api_secret; + private ?string $plain_api_secret = null; - /** - * @var string - * - * @ORM\Column(name="from_phone_number", type="string", nullable=true, length=200) - */ - private $from_phone_number = null; + #[ORM\Column(name: 'from_phone_number', type: Types::STRING, nullable: true, length: 200)] + private ?string $from_phone_number = null; - /** - * @var string - * - * @ORM\Column(name="include_routes", type="text", nullable=true) - */ - private $include_routes = null; + #[ORM\Column(name: 'include_routes', type: Types::TEXT, nullable: true)] + private ?string $include_routes = null; /** * Constructor. @@ -78,20 +58,16 @@ public function __construct() /** * Get id. - * - * @return int */ - public function getId() + public function getId(): ?int { return $this->id; } /** * Get api_key. - * - * @return string */ - public function getApiKey() + public function getApiKey(): ?string { return $this->api_key; } @@ -99,11 +75,9 @@ public function getApiKey() /** * Set api_key. * - * @param string $apiKey - * - * @return TwoFactorAuthConfig + * @return $this */ - public function setApiKey($apiKey) + public function setApiKey(?string $apiKey): self { $this->api_key = $apiKey; @@ -112,10 +86,8 @@ public function setApiKey($apiKey) /** * Get api_secret. - * - * @return string */ - public function getApiSecret() + public function getApiSecret(): ?string { return $this->api_secret; } @@ -123,11 +95,9 @@ public function getApiSecret() /** * Set api_secret. * - * @param string $apiSecret - * - * @return TwoFactorAuthConfig + * @return $this */ - public function setApiSecret($apiSecret) + public function setApiSecret(?string $apiSecret): self { $this->api_secret = $apiSecret; @@ -136,10 +106,8 @@ public function setApiSecret($apiSecret) /** * Get from phone number. - * - * @return string */ - public function getFromPhoneNumber() + public function getFromPhoneNumber(): ?string { return $this->from_phone_number; } @@ -147,18 +115,19 @@ public function getFromPhoneNumber() /** * Set from phone number. * - * @param string $fromPhoneNumber - * - * @return TwoFactorAuthConfig + * @return $this */ - public function setFromPhoneNumber(string $fromPhoneNumber) + public function setFromPhoneNumber(string $fromPhoneNumber): self { $this->from_phone_number = $fromPhoneNumber; return $this; } - public function addIncludeRoute(string $route) + /** + * @return $this + */ + public function addIncludeRoute(string $route): self { $routes = $this->getRoutes($this->getIncludeRoutes()); @@ -169,6 +138,9 @@ public function addIncludeRoute(string $route) return $this; } + /** + * @return list + */ private function getRoutes(?string $routes): array { if (!$routes) { @@ -180,10 +152,8 @@ private function getRoutes(?string $routes): array /** * Get include_routes. - * - * @return string|null */ - public function getIncludeRoutes() + public function getIncludeRoutes(): ?string { return $this->include_routes; } @@ -191,18 +161,19 @@ public function getIncludeRoutes() /** * Set include_routes. * - * @param string|null $include_routes - * - * @return TwoFactorAuthConfig + * @return $this */ - public function setIncludeRoutes($include_routes = null) + public function setIncludeRoutes(?string $include_routes = null): self { $this->include_routes = $include_routes; return $this; } - public function removeIncludeRoute(string $route) + /** + * @return $this + */ + public function removeIncludeRoute(string $route): self { $routes = $this->getRoutes($this->getIncludeRoutes()); @@ -214,26 +185,24 @@ public function removeIncludeRoute(string $route) return $this; } + /** + * @param array $routes + */ private function getRoutesAsString(array $routes): string { return implode(PHP_EOL, $routes); } /** - * @param string|null $plain_api_secret - * - * @return TwoFactorAuthConfig + * @return $this */ - public function setPlainApiSecret(?string $plain_api_secret): TwoFactorAuthConfig + public function setPlainApiSecret(?string $plain_api_secret): self { $this->plain_api_secret = $plain_api_secret; return $this; } - /** - * @return mixed - */ public function getPlainApiSecret(): ?string { return $this->plain_api_secret; diff --git a/Entity/TwoFactorAuthCustomerCookie.php b/Entity/TwoFactorAuthCustomerCookie.php index c88c42e..543f4ce 100644 --- a/Entity/TwoFactorAuthCustomerCookie.php +++ b/Entity/TwoFactorAuthCustomerCookie.php @@ -5,191 +5,126 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Entity; +namespace Plugin\TwoFactorAuthCustomer44\Entity; -use DateTime; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; use Eccube\Entity\Customer; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthCustomerCookieRepository; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * TwoFactorCustomerCookie - * - * @ORM\Table(name="plg_two_factor_customer_cookie") - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) - * @ORM\HasLifecycleCallbacks() - * @ORM\Entity(repositoryClass="Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository") - * @UniqueEntity("id") */ +#[ORM\Table(name: 'plg_two_factor_customer_cookie')] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'discriminator_type', type: Types::STRING, length: 255)] +#[ORM\HasLifecycleCallbacks] +#[ORM\Entity(repositoryClass: TwoFactorAuthCustomerCookieRepository::class)] +#[UniqueEntity('id')] class TwoFactorAuthCustomerCookie extends AbstractEntity { - /** - * @var int - * - * @ORM\Column(name="id", type="integer", options={"unsigned":true}) - * @ORM\Id - * @ORM\GeneratedValue(strategy="IDENTITY") - */ - private int $id; - /** - * @var Customer - * - * @ORM\ManyToOne(targetEntity="Eccube\Entity\Customer", inversedBy="TwoFactorCustomerCookie") - * @ORM\JoinColumns({ - * @ORM\JoinColumn(name="customer_id", referencedColumnName="id") - * }) - */ - private Customer $Customer; - /** - * @var string - * - * @ORM\Column(name="cookie_name", type="string", nullable=false, length=512) - */ + #[ORM\Column(name: 'id', type: Types::INTEGER, options: ['unsigned' => true])] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'IDENTITY')] + private ?int $id = null; + + #[ORM\ManyToOne(targetEntity: Customer::class, inversedBy: 'TwoFactorAuthCustomerCookies')] + #[ORM\JoinColumn(name: 'customer_id', referencedColumnName: 'id')] + private ?Customer $Customer = null; + + #[ORM\Column(name: 'cookie_name', type: Types::STRING, nullable: false, length: 512)] private string $cookie_name; - /** - * @var string - * - * @ORM\Column(name="cookie_value", type="string", nullable=false, length=512, unique=true) - */ + + #[ORM\Column(name: 'cookie_value', type: Types::STRING, nullable: false, length: 512, unique: true)] private string $cookie_value; - /** - * @var \DateTime - * - * @ORM\Column(name="cookie_expire_date", type="datetime", nullable=true) - */ - private ?\DateTime $cookie_expire_date; - /** - * @var \DateTime - * - * @ORM\Column(name="created_at", type="datetime", nullable=false) - */ - private \DateTime $createdAt; - /** - * @var \DateTime - * - * @ORM\Column(name="updated_at", type="datetime", nullable=false) - */ - private \DateTime $updatedAt; - - /** - * @ORM\PrePersist - * @ORM\PreUpdate - */ + + #[ORM\Column(name: 'cookie_expire_date', type: Types::DATETIME_MUTABLE, nullable: true)] + private ?\DateTime $cookie_expire_date = null; + + #[ORM\Column(name: 'created_at', type: Types::DATETIME_MUTABLE, nullable: false)] + private ?\DateTime $createdAt = null; + + #[ORM\Column(name: 'updated_at', type: Types::DATETIME_MUTABLE, nullable: false)] + private ?\DateTime $updatedAt = null; + + #[ORM\PrePersist] + #[ORM\PreUpdate] public function updatedTimestamps(): void { $this->setUpdatedAt(new \DateTime('now')); - if (!isset($this->createdAt) || $this->getCreatedAt() === null) { + if ($this->getCreatedAt() === null) { $this->setCreatedAt(new \DateTime('now')); } } - /** - * @return \DateTime - */ - public function getCreatedAt(): \DateTime + public function getCreatedAt(): ?\DateTime { return $this->createdAt; } - /** - * @param \DateTime $createdAt - */ public function setCreatedAt(\DateTime $createdAt): void { $this->createdAt = $createdAt; } - /** - * @return int - */ - public function getId(): int + public function getId(): ?int { return $this->id; } - /** - * @return Customer - */ - public function getCustomer(): Customer + public function getCustomer(): ?Customer { return $this->Customer; } - /** - * @param Customer $Customer - */ public function setCustomer(Customer $Customer): void { $this->Customer = $Customer; } - /** - * @return string - */ public function getCookieName(): string { return $this->cookie_name; } - /** - * @param string $cookie_name - */ public function setCookieName(string $cookie_name): void { $this->cookie_name = $cookie_name; } - /** - * @return string - */ public function getCookieValue(): string { return $this->cookie_value; } - /** - * @param string $cookie_value - */ public function setCookieValue(string $cookie_value): void { $this->cookie_value = $cookie_value; } - /** - * @return \DateTime - */ - public function getCookieExpireDate(): \DateTime + public function getCookieExpireDate(): ?\DateTime { return $this->cookie_expire_date; } - /** - * @param \DateTime $cookie_expire_date - */ - public function setCookieExpireDate(\DateTime $cookie_expire_date): void + public function setCookieExpireDate(?\DateTime $cookie_expire_date): void { $this->cookie_expire_date = $cookie_expire_date; } - /** - * @return \DateTime - */ - public function getUpdatedAt(): \DateTime + public function getUpdatedAt(): ?\DateTime { return $this->updatedAt; } - /** - * @param \DateTime $updatedAt - */ public function setUpdatedAt(\DateTime $updatedAt): void { $this->updatedAt = $updatedAt; diff --git a/Entity/TwoFactorAuthType.php b/Entity/TwoFactorAuthType.php index 0db26b0..1e02d88 100644 --- a/Entity/TwoFactorAuthType.php +++ b/Entity/TwoFactorAuthType.php @@ -5,59 +5,44 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Entity; +namespace Plugin\TwoFactorAuthCustomer44\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthTypeRepository; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** - * TwoFactorConfig - * - * @ORM\Table(name="plg_two_factor_auth_type") - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) - * @ORM\HasLifecycleCallbacks() - * @ORM\Entity(repositoryClass="Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository") - * @UniqueEntity("id") + * TwoFactorAuthType */ +#[ORM\Table(name: 'plg_two_factor_auth_type')] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'discriminator_type', type: Types::STRING, length: 255)] +#[ORM\HasLifecycleCallbacks] +#[ORM\Entity(repositoryClass: TwoFactorAuthTypeRepository::class)] +#[UniqueEntity('id')] class TwoFactorAuthType extends AbstractEntity { - /** - * @var int - * - * @ORM\Column(name="id", type="integer", options={"unsigned":true}) - * @ORM\Id - * @ORM\GeneratedValue(strategy="IDENTITY") - */ - private $id; + #[ORM\Column(name: 'id', type: Types::INTEGER, options: ['unsigned' => true])] + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'IDENTITY')] + private ?int $id = null; - /** - * @var string - * - * @ORM\Column(name="name", type="string", nullable=false, length=200, unique=true) - */ - private $name; + #[ORM\Column(name: 'name', type: Types::STRING, nullable: false, length: 200, unique: true)] + private ?string $name = null; - /** - * @var string - * - * @ORM\Column(name="route", type="string", nullable=false, length=200, unique=true) - */ - private $route = null; + #[ORM\Column(name: 'route', type: Types::STRING, nullable: false, length: 200, unique: true)] + private ?string $route = null; - /** - * @var boolean - * - * @ORM\Column(name="is_disabled", type="boolean", nullable=false) - */ - private $isDisabled = false; + #[ORM\Column(name: 'is_disabled', type: Types::BOOLEAN, nullable: false)] + private bool $isDisabled = false; /** * Constructor. @@ -68,20 +53,16 @@ public function __construct() /** * Get id. - * - * @return int */ - public function getId() + public function getId(): ?int { return $this->id; } /** * Get name. - * - * @return string */ - public function getName() + public function getName(): ?string { return $this->name; } @@ -89,11 +70,9 @@ public function getName() /** * Set name. * - * @param string $name - * - * @return TwoFactorAuthType + * @return $this */ - public function setName($name) + public function setName(string $name): self { $this->name = $name; @@ -102,10 +81,8 @@ public function setName($name) /** * Get route. - * - * @return string */ - public function getRoute() + public function getRoute(): ?string { return $this->route; } @@ -113,28 +90,20 @@ public function getRoute() /** * Set route. * - * @param string $route - * - * @return TwoFactorAuthType + * @return $this */ - public function setRoute($route) + public function setRoute(string $route): self { $this->route = $route; return $this; } - /** - * @return bool - */ public function isDisabled(): bool { return $this->isDisabled; } - /** - * @param bool $isDisabled - */ public function setIsDisabled(bool $isDisabled): void { $this->isDisabled = $isDisabled; diff --git a/Event.php b/Event.php index 54c7850..a9ee604 100644 --- a/Event.php +++ b/Event.php @@ -5,16 +5,16 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42; +namespace Plugin\TwoFactorAuthCustomer44; use Eccube\Event\TemplateEvent; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthTypeRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -25,7 +25,7 @@ class Event implements EventSubscriberInterface /** * @var bool */ - private bool $hasActiveAuthType; + private readonly bool $hasActiveAuthType; /** * Event constructor. @@ -34,9 +34,12 @@ class Event implements EventSubscriberInterface */ public function __construct(TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository) { - $this->hasActiveAuthType = $twoFactorAuthTypeRepository->count(['isDisabled' => false]) > 0; + $this->hasActiveAuthType = $twoFactorAuthTypeRepository->hasActiveType(); } + /** + * @return array + */ public static function getSubscribedEvents(): array { return [ @@ -51,15 +54,15 @@ public static function getSubscribedEvents(): array * * @param TemplateEvent $event */ - public function onRenderAdminShopSettingEdit(TemplateEvent $event) + public function onRenderAdminShopSettingEdit(TemplateEvent $event): void { // add 本人確認認証 twig - $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/shop_edit_sms.twig'; + $twig = '@TwoFactorAuthCustomer44/admin/shop_edit_sms.twig'; $event->addSnippet($twig); if ($this->hasActiveAuthType) { // add 2段階認証設定 twig - $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/shop_edit_tfa.twig'; + $twig = '@TwoFactorAuthCustomer44/admin/shop_edit_tfa.twig'; $event->addSnippet($twig); } } @@ -70,10 +73,10 @@ public function onRenderAdminShopSettingEdit(TemplateEvent $event) * * @param TemplateEvent $event */ - public function onRenderAdminCustomerEdit(TemplateEvent $event) + public function onRenderAdminCustomerEdit(TemplateEvent $event): void { // add twig - $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/customer_edit.twig'; + $twig = '@TwoFactorAuthCustomer44/admin/customer_edit.twig'; $event->addSnippet($twig); } } diff --git a/EventListener/CustomerPersonalValidationListener.php b/EventListener/CustomerPersonalValidationListener.php index 01ffb4f..c4a449d 100644 --- a/EventListener/CustomerPersonalValidationListener.php +++ b/EventListener/CustomerPersonalValidationListener.php @@ -5,23 +5,22 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\EventListener; +namespace Plugin\TwoFactorAuthCustomer44\EventListener; use Eccube\Entity\BaseInfo; use Eccube\Repository\BaseInfoRepository; use Eccube\Repository\CustomerRepository; use Eccube\Request\Context; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; +use Plugin\TwoFactorAuthCustomer44\Service\CustomerTwoFactorAuthService; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\KernelEvents; @@ -50,11 +49,7 @@ class CustomerPersonalValidationListener implements EventSubscriberInterface */ protected BaseInfoRepository $baseInfoRepository; /** - * @var CustomerRepository - */ - protected CustomerRepository $customerRepository; - /** - * @var BaseInfo|object|null + * @var BaseInfo|null */ protected $baseInfo; @@ -70,17 +65,16 @@ public function __construct( UrlGeneratorInterface $router, CustomerTwoFactorAuthService $customerTwoFactorAuthService, BaseInfoRepository $baseInfoRepository, - CustomerRepository $customerRepository + protected CustomerRepository $customerRepository, ) { $this->requestContext = $requestContext; $this->router = $router; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; $this->baseInfo = $baseInfoRepository->find(1); - $this->customerRepository = $customerRepository; } /** - * @return array + * @return array */ public static function getSubscribedEvents(): array { @@ -94,7 +88,7 @@ public static function getSubscribedEvents(): array * * @param ControllerArgumentsEvent $event */ - public function onKernelController(ControllerArgumentsEvent $event) + public function onKernelController(ControllerArgumentsEvent $event): void { if (!$event->isMainRequest()) { // サブリクエストの場合、処理なし @@ -108,8 +102,7 @@ public function onKernelController(ControllerArgumentsEvent $event) if ( ($this->baseInfo->isOptionCustomerActivate() && !$this->baseInfo->isOptionActivateDevice()) - || - !$this->baseInfo->isOptionCustomerActivate() + || !$this->baseInfo->isOptionCustomerActivate() ) { // デバイス認証なし かつ 2段階認証使用しない場合は処理なし return; @@ -143,7 +136,7 @@ private function isActivationRoute(string $route): bool * * @throws NotFoundHttpException */ - private function deviceAuth($event) + private function deviceAuth(mixed $event): void { // アクティベーション $secret_key = $event->getRequest()->attributes->get('secret_key'); @@ -165,9 +158,7 @@ private function deviceAuth($event) ['secret_key' => $secret_key] ); - $event->setController(function () use ($url) { - return new RedirectResponse($url, 302); - }); + $event->setController(fn () => new RedirectResponse($url, Response::HTTP_FOUND)); } } } diff --git a/EventListener/CustomerTwoFactorAuthListener.php b/EventListener/CustomerTwoFactorAuthListener.php index fdf0ddc..5dbe17c 100755 --- a/EventListener/CustomerTwoFactorAuthListener.php +++ b/EventListener/CustomerTwoFactorAuthListener.php @@ -5,13 +5,13 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\EventListener; +namespace Plugin\TwoFactorAuthCustomer44\EventListener; use Eccube\Common\EccubeConfig; use Eccube\Entity\BaseInfo; @@ -19,18 +19,19 @@ use Eccube\Entity\Master\CustomerStatus; use Eccube\Repository\BaseInfoRepository; use Eccube\Request\Context; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthCustomerCookieRepository; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthCustomerCookieRepository; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthTypeRepository; +use Plugin\TwoFactorAuthCustomer44\Service\CustomerTwoFactorAuthService; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\Event\LoginSuccessEvent; use Symfony\Component\Security\Http\Event\LogoutEvent; -use Symfony\Contracts\EventDispatcher\Event; class CustomerTwoFactorAuthListener implements EventSubscriberInterface { @@ -51,29 +52,25 @@ class CustomerTwoFactorAuthListener implements EventSubscriberInterface */ protected $customerTwoFactorAuthService; /** - * @var TwoFactorAuthTypeRepository - */ - protected TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository; - /** - * @var TwoFactorAuthCustomerCookieRepository - */ - protected TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository; - /** - * @var BaseInfo|object|null + * @var BaseInfo|null */ protected $baseInfo; /** - * @var Session + * @var SessionInterface */ - protected $session; + protected SessionInterface $session; /** * 通常(ログイン・マイページ)ルート. + * + * @var list */ - protected $default_routes; + protected array $default_routes; /** * 重要操作ルート. + * + * @var list */ - protected $include_routes; + protected array $include_routes; /** * @param Context $requestContext @@ -88,17 +85,15 @@ public function __construct( Context $requestContext, UrlGeneratorInterface $router, CustomerTwoFactorAuthService $customerTwoFactorAuthService, - TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, - TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository, + protected TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, + protected TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository, BaseInfoRepository $baseInfoRepository, - RequestStack $requestStack + RequestStack $requestStack, ) { $this->requestContext = $requestContext; $this->router = $router; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; $this->baseInfo = $baseInfoRepository->find(1); - $this->twoFactorAuthTypeRepository = $twoFactorAuthTypeRepository; - $this->twoFactorAuthCustomerCookieRepository = $twoFactorAuthCustomerCookieRepository; $this->session = $requestStack->getSession(); $this->default_routes = $this->customerTwoFactorAuthService->getDefaultAuthRoutes(); @@ -106,7 +101,7 @@ public function __construct( } /** - * @return array + * @return array */ public static function getSubscribedEvents(): array { @@ -122,7 +117,7 @@ public static function getSubscribedEvents(): array * * @param ControllerArgumentsEvent $event */ - public function onKernelController(ControllerArgumentsEvent $event) + public function onKernelController(ControllerArgumentsEvent $event): void { if (!$event->isMainRequest()) { // サブリクエストの場合、処理なし @@ -141,6 +136,9 @@ public function onKernelController(ControllerArgumentsEvent $event) $route = $event->getRequest()->attributes->get('_route'); $uri = $event->getRequest()->getRequestUri(); + if (!is_string($route)) { + return; + } $Customer = $this->requestContext->getCurrentUser(); @@ -163,10 +161,8 @@ public function onKernelController(ControllerArgumentsEvent $event) * ログイン完了 イベントハンドラ. * * @param LoginSuccessEvent $event - * - * @return RedirectResponse|void */ - public function onLoginSuccess(LoginSuccessEvent $event) + public function onLoginSuccess(LoginSuccessEvent $event): void { if ($this->requestContext->isAdmin()) { // バックエンドURLの場合処理なし @@ -178,21 +174,26 @@ public function onLoginSuccess(LoginSuccessEvent $event) return; } - if ($this->requestContext->getCurrentUser() === null) { + $Customer = $this->requestContext->getCurrentUser(); + if (!$Customer instanceof Customer) { // ログインしていない場合は処理なし return; } - if ($this->requestContext->getCurrentUser()->getTwoFactorAuthType() !== null && - $this->requestContext->getCurrentUser()->getTwoFactorAuthType()->isDisabled()) { + if ($Customer->getTwoFactorAuthType() !== null + && $Customer->getTwoFactorAuthType()->isDisabled()) { // ユーザーが選択した2段階認証方式は無効になっている場合、ログアウトさせる。 - return new RedirectResponse($this->router->generate('logout'), 302); + $event->setResponse(new RedirectResponse($this->router->generate('logout'), Response::HTTP_FOUND)); + + return; } + $route = $event->getRequest()->attributes->get('_route'); $this->multiFactorAuth( $event, - $this->requestContext->getCurrentUser(), - $event->getRequest()->attributes->get('_route')); + $Customer, + is_string($route) ? $route : '', + ); } /** @@ -202,7 +203,7 @@ public function onLoginSuccess(LoginSuccessEvent $event) * * @return void */ - public function logoutEvent(LogoutEvent $logoutEvent) + public function logoutEvent(LogoutEvent $logoutEvent): void { $Customer = $this->requestContext->getCurrentUser(); if ($Customer instanceof Customer) { @@ -211,7 +212,6 @@ public function logoutEvent(LogoutEvent $logoutEvent) } } - /** * ルート・URIが個別認証対象かチェック. * @@ -228,7 +228,7 @@ private function isDefaultRoute(string $route, string $uri): bool /** * ルート・URIが対象であるかチェック. * - * @param array $targetRoutes + * @param list $targetRoutes * @param string $route * @param string $uri * @@ -243,7 +243,7 @@ private function isTargetRoute(array $targetRoutes, string $route, string $uri): // URIで認証 foreach ($targetRoutes as $r) { - if ($r != '' && $r !== '/' && strpos($uri, $r) === 0) { + if ($r != '' && $r !== '/' && str_starts_with($uri, $r)) { return true; } } @@ -267,20 +267,20 @@ private function isIncludeRoute(string $route, string $uri): bool /** * 多要素認証. * - * @param Event $event + * @param ControllerArgumentsEvent|LoginSuccessEvent $event * @param Customer $Customer * @param string $route * - * @return mixed + * @return void */ - private function multiFactorAuth($event, $Customer, $route) + private function multiFactorAuth(ControllerArgumentsEvent|LoginSuccessEvent $event, Customer $Customer, string $route): void { if (!$this->baseInfo->isTwoFactorAuthUse()) { // MFA無効の場合処理なし return; } - if (count($this->twoFactorAuthTypeRepository->findBy(['isDisabled' => false])) == 0) { + if (!$this->twoFactorAuthTypeRepository->hasActiveType()) { // 2段階認証プラグインが有効化されていない場合処理なし return; } @@ -303,10 +303,10 @@ private function multiFactorAuth($event, $Customer, $route) /** * 多要素認証方式設定画面へリダイレクト. * - * @param Event $event + * @param ControllerArgumentsEvent|LoginSuccessEvent $event * @param string|null $route */ - private function selectAuthType($event, ?string $route) + private function selectAuthType(ControllerArgumentsEvent|LoginSuccessEvent $event, ?string $route): void { // [会員] 2段階認証が未設定の場合 // コールバックURLをセッションへ設定 @@ -314,13 +314,7 @@ private function selectAuthType($event, ?string $route) // 2段階認証選択画面へリダイレクト $url = $this->router->generate('plg_customer_2fa_auth_type_select', [], UrlGeneratorInterface::ABSOLUTE_PATH); - if ($event instanceof ControllerArgumentsEvent) { - $event->setController(function () use ($url) { - return new RedirectResponse($url, 302); - }); - } else { - $event->setResponse(new RedirectResponse($url, 302)); - } + $this->setRedirect($event, $url); } /** @@ -328,7 +322,7 @@ private function selectAuthType($event, ?string $route) * * @param string|null $route */ - private function setCallbackRoute(?string $route) + private function setCallbackRoute(?string $route): void { if ($route) { $this->session->set(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL, $route); @@ -338,33 +332,42 @@ private function setCallbackRoute(?string $route) /** * 2段階認証のディスパッチ. * - * @param Event $event + * @param ControllerArgumentsEvent|LoginSuccessEvent $event * @param Customer $Customer * @param string|null $route */ - private function auth($event, Customer $Customer, ?string $route) + private function auth(ControllerArgumentsEvent|LoginSuccessEvent $event, Customer $Customer, ?string $route): void { // コールバックURLをセッションへ設定 $this->setCallbackRoute($route); + + $authType = $Customer->getTwoFactorAuthType(); + if ($authType === null) { + return; + } + // 選択された多要素認証方式で指定されているルートへリダイレクト - if ($Customer->getTwoFactorAuthType() !== null && $Customer->getTwoFactorAuthType()->isDisabled()) { + if ($authType->isDisabled()) { // ユーザーが選択した2段階認証方式は無効になっている場合、ログアウトさせる。 - $event->setController(function () { - return new RedirectResponse($this->router->generate('logout'), 302); - }); + $this->setRedirect($event, $this->router->generate('logout')); return; } - $url = $this->router->generate($Customer->getTwoFactorAuthType()->getRoute()); + $routeName = $authType->getRoute(); + if ($routeName === null) { + return; + } + $this->setRedirect($event, $this->router->generate($routeName)); + } + + private function setRedirect(ControllerArgumentsEvent|LoginSuccessEvent $event, string $url): void + { if ($event instanceof ControllerArgumentsEvent) { - $event->setController(function () use ($url) { - return new RedirectResponse($url, 302); - }); + $event->setController(fn () => new RedirectResponse($url, Response::HTTP_FOUND)); } else { - $event->setResponse(new RedirectResponse($url, 302)); + $event->setResponse(new RedirectResponse($url, Response::HTTP_FOUND)); } } - } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php index 7efd56a..13c7fd8 100644 --- a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php @@ -5,18 +5,19 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type\Extension\Admin; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type\Extension\Admin; use Doctrine\ORM\EntityManagerInterface; use Eccube\Form\Type\Admin\ShopMasterType; use Eccube\Form\Type\ToggleSwitchType; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthType; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthTypeRepository; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; @@ -24,20 +25,13 @@ class TwoFactorAuthBaseSettingTypeExtension extends AbstractTypeExtension { - /** - * @var EntityManagerInterface - */ - protected EntityManagerInterface $entityManager; - /** * CouponDetailType constructor. * * @param EntityManagerInterface $entityManager */ - public function __construct( - EntityManagerInterface $entityManager - ) { - $this->entityManager = $entityManager; + public function __construct(protected EntityManagerInterface $entityManager) + { } /** @@ -52,9 +46,9 @@ public static function getExtendedTypes(): iterable * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { if (!empty($options['skip_add_form'])) { return; @@ -63,7 +57,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) { $form = $event->getForm(); - if ($this->entityManager->getRepository(TwoFactorAuthType::class)->count(['isDisabled' => false]) > 0) { + /** @var TwoFactorAuthTypeRepository $typeRepository */ + $typeRepository = $this->entityManager->getRepository(TwoFactorAuthType::class); + if ($typeRepository->hasActiveType()) { $form->add('two_factor_auth_use', ToggleSwitchType::class, [ 'required' => false, 'mapped' => true, @@ -71,9 +67,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) } $form->add('option_activate_device', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true, - ]); + 'required' => false, + 'mapped' => true, + ]); }); } } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php index fe6eae8..c1e8a69 100755 --- a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php @@ -5,19 +5,19 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type\Extension\Admin; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type\Extension\Admin; use Doctrine\ORM\EntityManagerInterface; use Eccube\Form\Type\Admin\CustomerType; use Eccube\Form\Type\PhoneNumberType; use Eccube\Form\Type\ToggleSwitchType; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; @@ -26,20 +26,13 @@ class TwoFactorAuthCustomerTypeExtension extends AbstractTypeExtension { - /** - * @var EntityManagerInterface - */ - protected EntityManagerInterface $entityManager; - /** * CouponDetailType constructor. * * @param EntityManagerInterface $entityManager */ - public function __construct( - EntityManagerInterface $entityManager - ) { - $this->entityManager = $entityManager; + public function __construct(protected EntityManagerInterface $entityManager) + { } /** @@ -54,9 +47,9 @@ public static function getExtendedTypes(): iterable * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { if (!empty($options['skip_add_form'])) { return; diff --git a/Form/Type/TwoFactorAuthAppTypeCustomer.php b/Form/Type/TwoFactorAuthAppTypeCustomer.php index 4f61f4e..eda2b4a 100644 --- a/Form/Type/TwoFactorAuthAppTypeCustomer.php +++ b/Form/Type/TwoFactorAuthAppTypeCustomer.php @@ -5,13 +5,13 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; @@ -24,38 +24,35 @@ class TwoFactorAuthAppTypeCustomer extends AbstractType /** * {@inheritdoc} */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add( 'device_token', TextType::class, [ - 'label' => 'front.setting.system.two_factor_auth.device_token', - 'required' => true, - 'constraints' => [ - new Assert\NotBlank(), - new Assert\Length([ - 'max' => 6, - 'min' => 6, - ]), - ], - 'attr' => [ - 'maxlength' => 6, - 'style' => 'width: 100px;', - ], - ]) + 'label' => 'front.setting.system.two_factor_auth.device_token', + 'required' => true, + 'constraints' => [ + new Assert\NotBlank(), + new Assert\Length(max: 6, min: 6), + ], + 'attr' => [ + 'maxlength' => 6, + 'style' => 'width: 100px;', + ], + ]) ->add( 'auth_key', HiddenType::class, [ - 'required' => true, - 'constraints' => [ - new Assert\NotBlank(), - ], - ]); + 'required' => true, + 'constraints' => [ + new Assert\NotBlank(), + ], + ]); } /** * {@inheritdoc} */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'plg_customer_2fa'; } diff --git a/Form/Type/TwoFactorAuthConfigType.php b/Form/Type/TwoFactorAuthConfigType.php index 00cd14f..54cd143 100644 --- a/Form/Type/TwoFactorAuthConfigType.php +++ b/Form/Type/TwoFactorAuthConfigType.php @@ -5,16 +5,16 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type; use Eccube\Common\EccubeConfig; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthConfig; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -33,61 +33,46 @@ class TwoFactorAuthConfigType extends AbstractType */ protected $eccubeConfig; - protected ValidatorInterface $validator; - /** * TwoFactorAuthConfigType constructor. * * @param EccubeConfig $eccubeConfig */ - public function __construct(EccubeConfig $eccubeConfig, ValidatorInterface $validator) + public function __construct(EccubeConfig $eccubeConfig, protected ValidatorInterface $validator) { $this->eccubeConfig = $eccubeConfig; - $this->validator = $validator; } - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('api_key', TextType::class, [ 'required' => true, 'constraints' => [ new Assert\NotBlank(), - new Assert\Length(['max' => $this->eccubeConfig['eccube_stext_len']]), - new Assert\Regex( - [ - 'pattern' => '/^[a-zA-Z0-9]+$/i', - 'message' => 'form_error.graph_only', - ] - ), + new Assert\Length(max: $this->eccubeConfig['eccube_stext_len']), + new Assert\Regex(pattern: '/^[a-zA-Z0-9]+$/i', message: 'form_error.graph_only'), ], ]) ->add('plain_api_secret', TextType::class, [ 'required' => true, 'constraints' => [ new Assert\NotBlank(), - new Assert\Length(['max' => $this->eccubeConfig['eccube_stext_len']]), + new Assert\Length(max: $this->eccubeConfig['eccube_stext_len']), ], ]) ->add('from_phone_number', TextType::class, [ 'required' => true, 'constraints' => [ new Assert\NotBlank(), - new Assert\Length(['max' => $this->eccubeConfig['eccube_stext_len']]), - new Assert\Regex( - [ - 'pattern' => '/^[0-9]+$/i', - 'message' => 'form_error.numeric_only', - ] - ), + new Assert\Length(max: $this->eccubeConfig['eccube_stext_len']), + new Assert\Regex(pattern: '/^[0-9]+$/i', message: 'form_error.numeric_only'), ], ]) ->add('include_routes', TextareaType::class, [ 'required' => false, 'constraints' => [ - new Assert\Length([ - 'max' => $this->eccubeConfig['eccube_ltext_len'], - ]), + new Assert\Length(max: $this->eccubeConfig['eccube_ltext_len']), ], ]); @@ -97,12 +82,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ($data['plain_api_secret'] !== $this->eccubeConfig['eccube_default_password']) { $errors = $this->validator->validate($data['plain_api_secret'], [ - new Assert\Regex([ - 'pattern' => '/^[a-zA-Z0-9]+$/i', - 'message' => 'form_error.graph_only', - ]), + new Assert\Regex(pattern: '/^[a-zA-Z0-9]+$/i', message: 'form_error.graph_only'), ]); - if ($errors) { + if (count($errors) > 0) { foreach ($errors as $error) { $form['plain_api_secret']->addError(new FormError($error->getMessage())); } @@ -116,7 +98,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) * * @see AbstractType::configureOptions */ - public function configureOptions(OptionsResolver $resolver) + public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => TwoFactorAuthConfig::class, diff --git a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php index f6e665c..915b652 100644 --- a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php +++ b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php @@ -5,13 +5,13 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type; use Eccube\Form\Type\PhoneNumberType; use Symfony\Component\Form\AbstractType; @@ -22,7 +22,7 @@ class TwoFactorAuthPhoneNumberTypeCustomer extends AbstractType /** * {@inheritdoc} */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('phone_number', PhoneNumberType::class, [ @@ -33,7 +33,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) /** * {@inheritdoc} */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'plg_customer_2fa'; } diff --git a/Form/Type/TwoFactorAuthSmsTypeCustomer.php b/Form/Type/TwoFactorAuthSmsTypeCustomer.php index 6907926..3ddc0b5 100644 --- a/Form/Type/TwoFactorAuthSmsTypeCustomer.php +++ b/Form/Type/TwoFactorAuthSmsTypeCustomer.php @@ -5,13 +5,13 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -23,31 +23,28 @@ class TwoFactorAuthSmsTypeCustomer extends AbstractType /** * {@inheritdoc} */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add( 'one_time_token', TextType::class, [ - 'label' => 'front.setting.system.two_factor_auth.one_time_token', - 'required' => true, - 'constraints' => [ - new Assert\NotBlank(), - new Assert\Length([ - 'max' => 6, - 'min' => 6, - ]), - ], - 'attr' => [ - 'maxlength' => 6, - 'style' => 'width: 100px;', - ], - ]); + 'label' => 'front.setting.system.two_factor_auth.one_time_token', + 'required' => true, + 'constraints' => [ + new Assert\NotBlank(), + new Assert\Length(max: 6, min: 6), + ], + 'attr' => [ + 'maxlength' => 6, + 'style' => 'width: 100px;', + ], + ]); } /** * {@inheritdoc} */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'plg_customer_2fa'; } diff --git a/Form/Type/TwoFactorAuthTypeCustomer.php b/Form/Type/TwoFactorAuthTypeCustomer.php index 5240525..555d34e 100644 --- a/Form/Type/TwoFactorAuthTypeCustomer.php +++ b/Form/Type/TwoFactorAuthTypeCustomer.php @@ -5,16 +5,16 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +namespace Plugin\TwoFactorAuthCustomer44\Form\Type; use Doctrine\ORM\EntityRepository; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; @@ -24,18 +24,16 @@ class TwoFactorAuthTypeCustomer extends AbstractType /** * {@inheritdoc} */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('two_factor_auth_type', EntityType::class, [ 'label' => 'front.setting.system.two_factor_auth.type', 'class' => TwoFactorAuthType::class, 'required' => true, - 'query_builder' => function (EntityRepository $er) { - return $er->createQueryBuilder('tfat') - ->where('tfat.isDisabled = :id') - ->setParameter('id', false); - }, + 'query_builder' => fn (EntityRepository $er) => $er->createQueryBuilder('tfat') + ->where('tfat.isDisabled = :id') + ->setParameter('id', false), 'choice_label' => 'name', 'mapped' => true, ]); @@ -44,7 +42,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) /** * {@inheritdoc} */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return 'plg_customer_2fa'; } diff --git a/PluginManager.php b/PluginManager.php index 4e40a36..83b2bc5 100644 --- a/PluginManager.php +++ b/PluginManager.php @@ -5,21 +5,21 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42; +namespace Plugin\TwoFactorAuthCustomer44; use Doctrine\ORM\EntityManagerInterface; +use Eccube\Common\EccubeConfig; use Eccube\Entity\Layout; use Eccube\Entity\Page; use Eccube\Entity\PageLayout; use Eccube\Plugin\AbstractPluginManager; -use Eccube\Common\EccubeConfig; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthConfig; use Psr\Container\ContainerInterface; use Symfony\Component\Filesystem\Filesystem; @@ -28,18 +28,22 @@ */ class PluginManager extends AbstractPluginManager { - // 設定対象ページ情報 - private $pages = [ - ['plg_customer_2fa_device_auth_send_onetime', 'デバイス認証送信先入力', 'TwoFactorAuthCustomer42/Resource/template/default/device_auth/send'], - ['plg_customer_2fa_device_auth_input_onetime', 'デバイス認証トークン入力', 'TwoFactorAuthCustomer42/Resource/template/default/device_auth/input'], - ['plg_customer_2fa_auth_type_select', '多要素認証方式選択', 'TwoFactorAuthCustomer42/Resource/template/default/tfa/select_type'], + /** + * 設定対象ページ情報 + * + * @var list + */ + private array $pages = [ + ['plg_customer_2fa_device_auth_send_onetime', 'デバイス認証送信先入力', 'TwoFactorAuthCustomer44/Resource/template/default/device_auth/send'], + ['plg_customer_2fa_device_auth_input_onetime', 'デバイス認証トークン入力', 'TwoFactorAuthCustomer44/Resource/template/default/device_auth/input'], + ['plg_customer_2fa_auth_type_select', '多要素認証方式選択', 'TwoFactorAuthCustomer44/Resource/template/default/tfa/select_type'], ]; /** - * @param array $meta + * @param array $meta * @param ContainerInterface $container */ - public function enable(array $meta, ContainerInterface $container) + public function enable(array $meta, ContainerInterface $container): void { $em = $container->get('doctrine')->getManager(); @@ -57,7 +61,7 @@ public function enable(array $meta, ContainerInterface $container) * * @param EntityManagerInterface $em */ - protected function createConfig(EntityManagerInterface $em) + protected function createConfig(EntityManagerInterface $em): void { $TwoFactorAuthConfig = $em->find(TwoFactorAuthConfig::class, 1); if ($TwoFactorAuthConfig) { @@ -75,17 +79,17 @@ protected function createConfig(EntityManagerInterface $em) * * @param ContainerInterface $container */ - protected function copyTwigFiles(ContainerInterface $container) + protected function copyTwigFiles(ContainerInterface $container): void { // テンプレートファイルコピー $templatePath = $container->get(EccubeConfig::class)->get('eccube_theme_front_dir') - . '/TwoFactorAuthCustomer42/Resource/template/default'; + .'/TwoFactorAuthCustomer44/Resource/template/default'; $fs = new Filesystem(); if ($fs->exists($templatePath)) { return; } $fs->mkdir($templatePath); - $fs->mirror(__DIR__ . '/Resource/template/default', $templatePath); + $fs->mirror(__DIR__.'/Resource/template/default', $templatePath); } /** @@ -93,7 +97,7 @@ protected function copyTwigFiles(ContainerInterface $container) * * @param EntityManagerInterface $em */ - protected function createPages(EntityManagerInterface $em) + protected function createPages(EntityManagerInterface $em): void { foreach ($this->pages as $p) { $hasPage = $em->getRepository(Page::class)->count(['url' => $p[0]]) > 0; @@ -123,10 +127,10 @@ protected function createPages(EntityManagerInterface $em) } /** - * @param array $meta + * @param array $meta * @param ContainerInterface $container */ - public function disable(array $meta, ContainerInterface $container) + public function disable(array $meta, ContainerInterface $container): void { $em = $container->get('doctrine')->getManager(); @@ -142,10 +146,10 @@ public function disable(array $meta, ContainerInterface $container) * * @param ContainerInterface $container */ - protected function removeTwigFiles(ContainerInterface $container) + protected function removeTwigFiles(ContainerInterface $container): void { $templatePath = $container->get(EccubeConfig::class)->get('eccube_theme_front_dir') - . '/TwoFactorAuthCustomer42'; + .'/TwoFactorAuthCustomer44'; $fs = new Filesystem(); $fs->remove($templatePath); } @@ -155,7 +159,7 @@ protected function removeTwigFiles(ContainerInterface $container) * * @param EntityManagerInterface $em */ - protected function removePages(EntityManagerInterface $em) + protected function removePages(EntityManagerInterface $em): void { foreach ($this->pages as $p) { $Page = $em->getRepository(Page::class)->findOneBy(['url' => $p[0]]); @@ -171,17 +175,16 @@ protected function removePages(EntityManagerInterface $em) } /** - * @param array $meta + * @param array $meta * @param ContainerInterface $container */ - public function uninstall(array $meta, ContainerInterface $container) + public function uninstall(array $meta, ContainerInterface $container): void { - $em = $container->get('doctrine')->getManager(); - // twigファイルを削除 $this->removeTwigFiles($container); // ページ削除 + $em = $container->get('doctrine')->getManager(); $this->removePages($em); } } diff --git a/README.md b/README.md index f17f5a0..5c0d3d4 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# 2段階認証プラグイン +# 2段階認証プラグイン (EC-CUBE 4.4) + +EC-CUBE 4.2/4.3 向け `TwoFactorAuthCustomer42` を EC-CUBE 4.4 / Symfony 7.4 向け `TwoFactorAuthCustomer44` に移行したプラグインです。 diff --git a/Repository/TwoFactorAuthConfigRepository.php b/Repository/TwoFactorAuthConfigRepository.php index b024e34..2202ab5 100644 --- a/Repository/TwoFactorAuthConfigRepository.php +++ b/Repository/TwoFactorAuthConfigRepository.php @@ -5,24 +5,25 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Repository; +namespace Plugin\TwoFactorAuthCustomer44\Repository; use Doctrine\Persistence\ManagerRegistry; use Eccube\Repository\AbstractRepository; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthConfig; /** * TwoFactorAuthConfigRepository. * * This class was generated by the Doctrine ORM. Add your own custom * repository methods below. + * + * @extends AbstractRepository */ class TwoFactorAuthConfigRepository extends AbstractRepository { @@ -37,9 +38,9 @@ public function __construct(ManagerRegistry $registry) } /** - * @return object|TwoFactorAuthConfig|TwoFactorAuthCustomerCookie|null $result + * @return TwoFactorAuthConfig|null */ - public function findOne() + public function findOne(): ?TwoFactorAuthConfig { return $this->findOneBy([], ['id' => 'DESC']); } diff --git a/Repository/TwoFactorAuthCustomerCookieRepository.php b/Repository/TwoFactorAuthCustomerCookieRepository.php index 8d7d4f5..0e1ab87 100644 --- a/Repository/TwoFactorAuthCustomerCookieRepository.php +++ b/Repository/TwoFactorAuthCustomerCookieRepository.php @@ -5,26 +5,28 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Repository; +namespace Plugin\TwoFactorAuthCustomer44\Repository; use Carbon\Carbon; use Doctrine\Persistence\ManagerRegistry; use Eccube\Entity\Customer; use Eccube\Repository\AbstractRepository; use Eccube\Util\StringUtil; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthCustomerCookie; /** - * TwoFactorAuthConfigRepository. + * TwoFactorAuthCustomerCookieRepository. * * This class was generated by the Doctrine ORM. Add your own custom * repository methods below. + * + * @extends AbstractRepository */ class TwoFactorAuthCustomerCookieRepository extends AbstractRepository { @@ -52,10 +54,8 @@ public function generateCookieData( Customer $customer, string $cookieName, int $expireSeconds, - int $CookieValueCharacterLength + int $CookieValueCharacterLength, ): TwoFactorAuthCustomerCookie { - /** @var TwoFactorAuthCustomerCookie[]|null $previousCookies */ - $previousCookies = $this->findOldCookies($customer, $cookieName); foreach ($previousCookies as $cookie) { $this->getEntityManager()->remove($cookie); @@ -78,9 +78,9 @@ public function generateCookieData( * @param Customer $customer * @param string $cookieName * - * @return float|int|mixed|string + * @return list */ - public function findOldCookies(Customer $customer, string $cookieName) + public function findOldCookies(Customer $customer, string $cookieName): array { $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); @@ -88,11 +88,9 @@ public function findOldCookies(Customer $customer, string $cookieName) ->where('tfcc.Customer = :customer_id') ->andWhere('tfcc.cookie_name = :cookie_name') ->andWhere('tfcc.cookie_expire_date < :expire_date') - ->setParameters([ - 'customer_id' => $customer->getId(), - 'cookie_name' => $cookieName, - 'expire_date' => $expireDate, - ]) + ->setParameter('customer_id', $customer->getId()) + ->setParameter('cookie_name', $cookieName) + ->setParameter('expire_date', $expireDate) ->getQuery() ->getResult(); } @@ -100,19 +98,20 @@ public function findOldCookies(Customer $customer, string $cookieName) /** * @return TwoFactorAuthCustomerCookie|null $result */ - public function findOne() + public function findOne(): ?TwoFactorAuthCustomerCookie { return $this->findOneBy([], ['id' => 'DESC']); } - /*** + /** * 有効クッキーを取得する * * @param Customer $customer * @param string $cookieName - * @return TwoFactorAuthCustomerCookie[]|null + * + * @return list */ - public function searchForCookie(Customer $customer, string $cookieName) + public function searchForCookie(Customer $customer, string $cookieName): array { $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); @@ -120,21 +119,19 @@ public function searchForCookie(Customer $customer, string $cookieName) ->where('tfcc.Customer = :customer_id') ->andWhere('tfcc.cookie_name = :cookie_name') ->andWhere('tfcc.cookie_expire_date > :expire_date') - ->setParameters([ - 'customer_id' => $customer->getId(), - 'cookie_name' => $cookieName, - 'expire_date' => $expireDate, - ]) + ->setParameter('customer_id', $customer->getId()) + ->setParameter('cookie_name', $cookieName) + ->setParameter('expire_date', $expireDate) ->getQuery() ->getResult(); } - /*** + /** * 会員のクッキーを削除 * * @param Customer $customer */ - public function deleteByCustomer(Customer $customer) + public function deleteByCustomer(Customer $customer): void { $em = $this->getEntityManager(); $em->beginTransaction(); @@ -150,5 +147,4 @@ public function deleteByCustomer(Customer $customer) $em->commit(); } - } diff --git a/Repository/TwoFactorAuthTypeRepository.php b/Repository/TwoFactorAuthTypeRepository.php index 5672da0..baed146 100644 --- a/Repository/TwoFactorAuthTypeRepository.php +++ b/Repository/TwoFactorAuthTypeRepository.php @@ -5,23 +5,25 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Repository; +namespace Plugin\TwoFactorAuthCustomer44\Repository; use Doctrine\Persistence\ManagerRegistry; use Eccube\Repository\AbstractRepository; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthType; /** * TwoFactorAuthTypeRepository. * * This class was generated by the Doctrine ORM. Add your own custom * repository methods below. + * + * @extends AbstractRepository */ class TwoFactorAuthTypeRepository extends AbstractRepository { @@ -36,10 +38,25 @@ public function __construct(ManagerRegistry $registry) } /** - * @return object|TwoFactorAuthType|null $result + * @return TwoFactorAuthType|null */ - public function findOne() + public function findOne(): ?TwoFactorAuthType { return $this->findOneBy([], ['id' => 'DESC']); } + + /** + * 有効な二段階認証方式が1件以上あるか. + */ + public function hasActiveType(): bool + { + $count = (int) $this->createQueryBuilder('t') + ->select('COUNT(t.id)') + ->where('t.isDisabled = :disabled') + ->setParameter('disabled', false) + ->getQuery() + ->getSingleScalarResult(); + + return $count > 0; + } } diff --git a/Resource/.php-cs-fixer.dist.php b/Resource/.php-cs-fixer.dist.php new file mode 100644 index 0000000..79d83ee --- /dev/null +++ b/Resource/.php-cs-fixer.dist.php @@ -0,0 +1,57 @@ + true, + 'array_syntax' => ['syntax' => 'short'], + 'phpdoc_align' => false, + 'phpdoc_summary' => false, + 'phpdoc_annotation_without_dot' => false, + 'no_superfluous_phpdoc_tags' => false, + 'increment_style' => false, + 'yoda_style' => false, + 'header_comment' => ['header' => $header], + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_param_order' => true, + 'phpdoc_to_comment' => false, // /** @var */ を変換してしまうため + 'phpdoc_trim' => true, + 'global_namespace_import' => [ + 'import_classes' => false, + 'import_constants' => false, + 'import_functions' => false, + ], + // PHPDocの型をネイティブ型へ + 'phpdoc_to_param_type' => true, + 'phpdoc_to_return_type' => true, + // プロパティのネイティブ型化は無効。EC-CUBE のテスト基盤が tearDown で全プロパティに + // null を代入するため、テストプロパティを非null native 型にすると TypeError になる。 + 'phpdoc_to_property_type' => false, +]; + +$finder = \PhpCsFixer\Finder::create() + ->in(dirname(__DIR__)) + ->exclude(['vendor', 'node_modules', 'Resource']) + ->name('*.php') +; +$config = new \PhpCsFixer\Config(); + +return $config + ->setRules($rules) + ->setFinder($finder) + ->setRiskyAllowed(true) + ->setUnsupportedPhpVersionAllowed(true) +; diff --git a/Resource/rector.php b/Resource/rector.php new file mode 100644 index 0000000..46556a5 --- /dev/null +++ b/Resource/rector.php @@ -0,0 +1,62 @@ +withPhpVersion(PhpVersion::PHP_82) + // プラグインのソースディレクトリ + ->withPaths([ + dirname(__DIR__).'/Controller', + dirname(__DIR__).'/Entity', + dirname(__DIR__).'/Form', + dirname(__DIR__).'/Repository', + dirname(__DIR__).'/Service', + dirname(__DIR__).'/EventListener', + dirname(__DIR__).'/PluginManager.php', + dirname(__DIR__).'/Event.php', + ]) + ->withSkip([ + dirname(__DIR__).'/vendor', + dirname(__DIR__).'/node_modules', + ]) + ->withSets([ + LevelSetList::UP_TO_PHP_82, + // rector 2.6.2 でバージョン別のセット定数 (SYMFONY_74 等) は撤去された。 + // 各ルールが composer.json を見て、インストール済みバージョンに合うものだけ実行する。 + SymfonySetList::COMPOSER_BASED, + SymfonySetList::SYMFONY_CODE_QUALITY, + DoctrineSetList::DOCTRINE_CODE_QUALITY, + DoctrineSetList::COMPOSER_BASED, + DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES, + ]) + // Symfony/Doctrine 等のアノテーション → アトリビュート変換を有効化 + ->withAttributesSets() + // #[Route] は付与されるが use 文が旧 Annotation のまま残るため Attribute へ統一する + ->withConfiguredRule(RenameClassRector::class, [ + 'Symfony\Component\Routing\Annotation\Route' => 'Symfony\Component\Routing\Attribute\Route', + ]) + ->withImportNames( + importShortClasses: false, + importDocBlockNames: true, + importNames: true + ) + ->withParallel(); diff --git a/Resource/template/admin/config.twig b/Resource/template/admin/config.twig index 2c87445..e6c61c3 100644 --- a/Resource/template/admin/config.twig +++ b/Resource/template/admin/config.twig @@ -9,7 +9,7 @@ {% block main %} -
+ {{ form_widget(form._token) }}
diff --git a/Service/CustomerTwoFactorAuthService.php b/Service/CustomerTwoFactorAuthService.php index 99d78af..0df1963 100644 --- a/Service/CustomerTwoFactorAuthService.php +++ b/Service/CustomerTwoFactorAuthService.php @@ -5,31 +5,32 @@ * * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. * - * http://www.ec-cube.co.jp/ + * https://www.ec-cube.co.jp/ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -namespace Plugin\TwoFactorAuthCustomer42\Service; +namespace Plugin\TwoFactorAuthCustomer44\Service; use Doctrine\ORM\EntityManagerInterface; use Eccube\Common\EccubeConfig; use Eccube\Entity\BaseInfo; use Eccube\Entity\Customer; use Eccube\Repository\BaseInfoRepository; -use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository; -use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthCustomerCookieRepository; +use Plugin\TwoFactorAuthCustomer44\Entity\TwoFactorAuthConfig; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthConfigRepository; +use Plugin\TwoFactorAuthCustomer44\Repository\TwoFactorAuthCustomerCookieRepository; use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface; -use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; +use Symfony\Contracts\Service\Attribute\Required; use Twilio\Exceptions\ConfigurationException; use Twilio\Exceptions\TwilioException; +use Twilio\Rest\Api\V2010\Account\MessageInstance; use Twilio\Rest\Client; class CustomerTwoFactorAuthService @@ -52,10 +53,6 @@ class CustomerTwoFactorAuthService * @var EccubeConfig */ protected $eccubeConfig; - /** - * @var EncoderFactoryInterface - */ - protected $encoderFactory; /** * @var RequestStack */ @@ -81,11 +78,7 @@ class CustomerTwoFactorAuthService */ protected $route_expire; /** - * @var EntityManagerInterface - */ - private $entityManager; - /** - * @var BaseInfo|object|null + * @var BaseInfo|null */ private $baseInfo; @@ -97,12 +90,12 @@ class CustomerTwoFactorAuthService /** * @var int */ - private int $tokenLength; + private readonly int $tokenLength; /** - * @var array + * @var list */ - private $default_tfa_routes = [ + private array $default_tfa_routes = [ 'login', 'mypage_login', 'mypage', @@ -115,17 +108,7 @@ class CustomerTwoFactorAuthService 'shopping_login', ]; - /** - * @var TwoFactorAuthCustomerCookieRepository - */ - private TwoFactorAuthCustomerCookieRepository $twoFactorCustomerCookieRepository; - - /** - * @var PasswordHasherFactoryInterface - */ - private PasswordHasherFactoryInterface $hashFactory; - - private int $tokenActiveDurationSeconds; + private readonly int $tokenActiveDurationSeconds; /** * constructor. @@ -138,15 +121,14 @@ class CustomerTwoFactorAuthService * @param PasswordHasherFactoryInterface $hashFactory */ public function __construct( - EntityManagerInterface $entityManager, + private readonly EntityManagerInterface $entityManager, EccubeConfig $eccubeConfig, BaseInfoRepository $baseInfoRepository, RequestStack $requestStack, TwoFactorAuthConfigRepository $twoFactorAuthConfigRepository, - TwoFactorAuthCustomerCookieRepository $twoFactorCustomerCookieRepository, - PasswordHasherFactoryInterface $hashFactory + private readonly TwoFactorAuthCustomerCookieRepository $twoFactorCustomerCookieRepository, + private readonly PasswordHasherFactoryInterface $hashFactory, ) { - $this->entityManager = $entityManager; $this->eccubeConfig = $eccubeConfig; $this->baseInfo = $baseInfoRepository->find(1); @@ -161,21 +143,17 @@ public function __construct( $this->tokenActiveDurationSeconds = (int) $this->eccubeConfig->get('plugin_eccube_2fa_one_time_token_expire_after_seconds'); $this->twoFactorAuthConfig = $twoFactorAuthConfigRepository->findOne(); - $this->twoFactorCustomerCookieRepository = $twoFactorCustomerCookieRepository; - $this->hashFactory = $hashFactory; } /** - * @return array + * @return list */ - public function getDefaultAuthRoutes() + public function getDefaultAuthRoutes(): array { return $this->default_tfa_routes; } - /** - * @required - */ + #[Required] public function setContainer(ContainerBagInterface $container): ?ContainerBagInterface { $previous = $this->container; @@ -188,11 +166,11 @@ public function setContainer(ContainerBagInterface $container): ?ContainerBagInt * 2段階認証用Cookie生成. * * @param Customer $Customer - * @param null $route + * @param string|null $route * * @return Cookie */ - public function createAuthedCookie($Customer, $route = null): Cookie + public function createAuthedCookie(Customer $Customer, ?string $route = null): Cookie { $expire = $this->expire; $cookieName = $this->cookieName; @@ -210,30 +188,31 @@ public function createAuthedCookie($Customer, $route = null): Cookie /** * 要認証ルートを取得. * - * @return array + * @return list */ public function getIncludeRoutes(): array { - $routes = []; $include = $this->twoFactorAuthConfig->getIncludeRoutes(); - if ($include) { - $routes = preg_split('/\R/', $include); + if (!$include) { + return []; } - return $routes; + $routes = preg_split('/\R/', $include); + + return $routes === false ? [] : $routes; } /** * 認証済みか? * * @param Customer $Customer - * @param null $route + * @param string|null $route * - * @return boolean + * @return bool */ - public function isAuthed(Customer $Customer, $route = null): bool + public function isAuthed(Customer $Customer, ?string $route = null): bool { - if (!$Customer->getTwoFactorAuthType() === null) { + if ($Customer->getTwoFactorAuthType() === null) { return false; } @@ -270,7 +249,6 @@ public function isRouteAuthed(Customer $Customer, string $cookieName, int $expir if ($json = $this->request->cookies->get($cookieName)) { $configs = json_decode($json); - /** @var TwoFactorAuthCustomerCookie[]|null $activeCookies */ $activeCookies = $this ->twoFactorCustomerCookieRepository ->searchForCookie($Customer, $cookieName); @@ -303,9 +281,9 @@ public function isRouteAuthed(Customer $Customer, string $cookieName, int $expir * @param string $cookieName * @param int $expire * - * @return mixed + * @return Cookie */ - public function createRouteAuthCookie(Customer $Customer, string $cookieName, int $expire) + public function createRouteAuthCookie(Customer $Customer, string $cookieName, int $expire): Cookie { return $this->entityManager->wrapInTransaction(function (EntityManagerInterface $em) use ($expire, $cookieName, $Customer) { $cookieData = $this->twoFactorCustomerCookieRepository->generateCookieData( @@ -357,13 +335,15 @@ public function isEnabled(): bool * * TODO: APIエラーハンドルの追加、 * - * @param $phoneNumber - * @param $body + * @param string $phoneNumber + * @param string $body + * + * @return MessageInstance + * * @throws ConfigurationException * @throws TwilioException - * @return \Twilio\Rest\Api\V2010\Account\MessageInstance */ - public function sendBySms($phoneNumber, $body) + public function sendBySms(string $phoneNumber, string $body): MessageInstance { // Twilio // SMS送信(現在国内電話番号のみ対象) @@ -388,12 +368,12 @@ public function sendBySms($phoneNumber, $body) * * @return void */ - public function clear2AuthCookies(Request $request, Response $response) + public function clear2AuthCookies(Request $request, Response $response): void { foreach ($request->cookies->all() as $key => $cookie) { if ( - $this->str_contains($key, $this->cookieName) || - $this->str_contains($key, $this->routeCookieName) + $this->str_contains($key, $this->cookieName) + || $this->str_contains($key, $this->routeCookieName) ) { // クッキーを消す $response->headers->clearCookie($key); @@ -430,23 +410,24 @@ public function hashOneTimeToken(string $token): string public function verifyOneTimeToken(string $hashedToken, string $token): bool { - if ($this->hashFactory->getPasswordHasher(Customer::class)->verify($hashedToken, $token)) { - return true; - } elseif ($hashedToken === $this->hashOneTimeToken($token)) { - return true; - } else { - return false; - } + if ($this->hashFactory->getPasswordHasher(Customer::class)->verify($hashedToken, $token)) { + return true; + } elseif ($hashedToken === $this->hashOneTimeToken($token)) { + return true; + } + + return false; } - /*** + /** * @param string $haystack * @param string $needle + * * @return bool * * @deprecated ECCUBEの最低PHPバージョンは8.0になったら, この関数を消してphp8.0からのstr_containsを利用する */ - private function str_contains(string $haystack, string $needle) + private function str_contains(string $haystack, string $needle): bool { return $needle !== '' && mb_strpos($haystack, $needle) !== false; } diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php new file mode 100644 index 0000000..e465994 --- /dev/null +++ b/Tests/bootstrap.php @@ -0,0 +1,19 @@ +load($envFile); +} diff --git a/composer.json b/composer.json index 3d76137..db5265b 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { - "name": "ec-cube/twofactorauthcustomer42", - "version": "4.3.0", - "description": "2 factor authentication for Customers EC-CUBE42", + "name": "ec-cube/twofactorauthcustomer44", + "version": "4.4.0", + "description": "2 factor authentication for Customers EC-CUBE 4.4", "type": "eccube-plugin", "extra": { - "code": "TwoFactorAuthCustomer42" + "code": "TwoFactorAuthCustomer44" }, "require": { "ec-cube/plugin-installer": "^2.0", diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..ec5115d --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,28 @@ +parameters: + level: 6 + paths: + - . + excludePaths: + - Resource/* + - Tests/bootstrap.php + doctrine: + objectManagerLoader: ../../../tests/object-manager.php + ormRepositoryClass: Eccube\Repository\AbstractRepository + # stubFiles は doctrine.objectManagerLoader が Customer/BaseInfo の + # リフレクションを上書きするため EntityExtension メソッドには効かない。 + ignoreErrors: + - + message: '#Call to an undefined method Eccube\\Entity\\Customer::(get|set|is)(DeviceAuth|DeviceAuthed|TwoFactorAuth).*#' + - + message: '#Call to an undefined method Eccube\\Entity\\BaseInfo::(is|set)(TwoFactorAuthUse|OptionActivateDevice)\(\)#' + # twilio/sdk のクラスが PHPStan のオートロードに乗らない + - + message: '#Twilio\\#' + # EntityExtension の trait は実行時 proxy に載るため、解析上は未使用になる + - + identifier: trait.unused + # EC-CUBE 本体と同様。new Entity() 時に nullable が必要なプロパティと DB 非 null の差 + - + message: "#^Property .+::\\$.+ type mapping mismatch: property can contain .+\\|null but database expects .+\\.$#" + identifier: doctrine.columnType + reportUnmatchedIgnoredErrors: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist index dd5996d..274abad 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,20 +1,20 @@ + - - - - - - - - + + + + + + + @@ -24,26 +24,20 @@ - - - - - + + + ./ - - ./Tests - ./Resource - ./PluginManager.php - - - + + + ./Tests + ./Resource + ./PluginManager.php + + - - - - + + + +