diff --git a/.github/workflows/ab-testing.yml b/.github/workflows/ab-testing.yml new file mode 100644 index 0000000..a793dde --- /dev/null +++ b/.github/workflows/ab-testing.yml @@ -0,0 +1,947 @@ +name: Apache bench (HTTP load speed) testing for EC-CUBE +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: +jobs: + load-test: + name: Apache bench (HTTP load speed) testing for EC-CUBE + runs-on: ubuntu-latest + steps: + # POSTGRES SQL + # BASE PRODUCTS + # PLUGIN + - name: PGSQL BASE PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml up -d --wait + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download Plugin + uses: actions/checkout@master + with: + path: app/Plugin/TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomerApp42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomerApp42 + - name: Download Plugin TwoFactorAuthCustomerSms42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 + path: app/Plugin/TwoFactorAuthCustomerSms42 + - 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 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 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 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 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 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 + - 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 + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml up -d --wait + - name: Request home page - PGSQL PLUGIN BASE + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-home_5.txt + export PG_4_1_HOME_1="$(tail -n +23 pg-plugin-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_HOME_2="$(tail -n +23 pg-plugin-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_HOME_3="$(tail -n +23 pg-plugin-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_HOME_4="$(tail -n +23 pg-plugin-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_HOME_5="$(tail -n +23 pg-plugin-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_HOME_RPS_1="$(tail -n +20 pg-plugin-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_HOME_RPS_2="$(tail -n +20 pg-plugin-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_HOME_RPS_3="$(tail -n +20 pg-plugin-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_HOME_RPS_4="$(tail -n +20 pg-plugin-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_HOME_RPS_5="$(tail -n +20 pg-plugin-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_4_1_HOME_1 + $PG_4_1_HOME_2 + $PG_4_1_HOME_3 + $PG_4_1_HOME_4 + $PG_4_1_HOME_5" | bc -l) + RPS_SUM=$(echo "$PG_4_1_HOME_RPS_1 + $PG_4_1_HOME_RPS_2 + $PG_4_1_HOME_RPS_3 + $PG_4_1_HOME_RPS_4 + $PG_4_1_HOME_RPS_5" | bc -l) + COUNT=5 + export PSQL_PLUGIN_BASE_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PSQL_PLUGIN_BASE_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PSQL_PLUGIN_BASE_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PSQL_PLUGIN_BASE_HOME_RPS_RESULT}" + echo "PSQL_PLUGIN_BASE_HOME_RESULT=${PSQL_PLUGIN_BASE_HOME_RESULT}" >> $GITHUB_ENV + echo "PSQL_PLUGIN_BASE_HOME_RPS_RESULT=${PSQL_PLUGIN_BASE_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - PGSQL PLUGIN BASE + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-base-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-base-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-base-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-base-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-base-list_5.txt + export PG_4_1_LIST_1="$(tail -n +23 pg-plugin-base-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_LIST_2="$(tail -n +23 pg-plugin-base-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_LIST_3="$(tail -n +23 pg-plugin-base-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_LIST_4="$(tail -n +23 pg-plugin-base-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_LIST_5="$(tail -n +23 pg-plugin-base-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_4_1_LIST_RPS_1="$(tail -n +20 pg-plugin-base-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_LIST_RPS_2="$(tail -n +20 pg-plugin-base-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_LIST_RPS_3="$(tail -n +20 pg-plugin-base-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_LIST_RPS_4="$(tail -n +20 pg-plugin-base-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_4_1_LIST_RPS_5="$(tail -n +20 pg-plugin-base-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_4_1_LIST_1 + $PG_4_1_LIST_2 + $PG_4_1_LIST_3 + $PG_4_1_LIST_4 + $PG_4_1_LIST_5" | bc -l) + RPS_SUM=$(echo "$PG_4_1_LIST_RPS_1 + $PG_4_1_LIST_RPS_2 + $PG_4_1_LIST_RPS_3 + $PG_4_1_LIST_RPS_4 + $PG_4_1_LIST_RPS_5" | bc -l) + COUNT=5 + export PSQL_PLUGIN_BASE_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PSQL_PLUGIN_BASE_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PSQL_PLUGIN_BASE_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PSQL_PLUGIN_BASE_LIST_RPS_RESULT}" + echo "PSQL_PLUGIN_BASE_LIST_RESULT=${PSQL_PLUGIN_BASE_LIST_RESULT}" >> $GITHUB_ENV + echo "PSQL_PLUGIN_BASE_LIST_RPS_RESULT=${PSQL_PLUGIN_BASE_LIST_RPS_RESULT}" >> $GITHUB_ENV + # Upload Evidence + - name: Drop PGSQL ECCUBE for 4.2 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # PGSQL + # BASE PRODUCTS + # NO PLUGIN + - name: PGSQL BASE NO PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Setup to EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml up -d --wait + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Wait 2 minutes for the database to load, (as I do not know the databases active state) + run: sleep 120s + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml up -d --wait + - name: Request home page - PGSQL NO PLUGIN BASE + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_5.txt + export PG_NO_PLUGIN_BASE_HOME_1="$(tail -n +23 pg-no-plugin-10000-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_HOME_2="$(tail -n +23 pg-no-plugin-10000-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_HOME_3="$(tail -n +23 pg-no-plugin-10000-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_HOME_4="$(tail -n +23 pg-no-plugin-10000-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_HOME_5="$(tail -n +23 pg-no-plugin-10000-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_HOME_RPS_1="$(tail -n +20 pg-no-plugin-10000-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_HOME_RPS_2="$(tail -n +20 pg-no-plugin-10000-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_HOME_RPS_3="$(tail -n +20 pg-no-plugin-10000-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_HOME_RPS_4="$(tail -n +20 pg-no-plugin-10000-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_HOME_RPS_5="$(tail -n +20 pg-no-plugin-10000-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_NO_PLUGIN_BASE_HOME_1 + $PG_NO_PLUGIN_BASE_HOME_2 + $PG_NO_PLUGIN_BASE_HOME_3 + $PG_NO_PLUGIN_BASE_HOME_4 + $PG_NO_PLUGIN_BASE_HOME_5" | bc -l) + RPS_SUM=$(echo "$PG_NO_PLUGIN_BASE_HOME_RPS_1 + $PG_NO_PLUGIN_BASE_HOME_RPS_2 + $PG_NO_PLUGIN_BASE_HOME_RPS_3 + $PG_NO_PLUGIN_BASE_HOME_RPS_4 + $PG_NO_PLUGIN_BASE_HOME_RPS_5" | bc -l) + COUNT=5 + export PSQL_NO_PLUGIN_BASE_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PSQL_NO_PLUGIN_BASE_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" + echo "PSQL_NO_PLUGIN_BASE_HOME_RESULT=${PSQL_NO_PLUGIN_BASE_HOME_RESULT}" >> $GITHUB_ENV + echo "PSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT=${PSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - PGSQL NO PLUGIN BASE + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_5.txt + export PG_NO_PLUGIN_BASE_LIST_1="$(tail -n +23 pg-no-plugin-10000-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_LIST_2="$(tail -n +23 pg-no-plugin-10000-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_LIST_3="$(tail -n +23 pg-no-plugin-10000-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_LIST_4="$(tail -n +23 pg-no-plugin-10000-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_LIST_5="$(tail -n +23 pg-no-plugin-10000-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_BASE_LIST_RPS_1="$(tail -n +20 pg-no-plugin-10000-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_LIST_RPS_2="$(tail -n +20 pg-no-plugin-10000-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_LIST_RPS_3="$(tail -n +20 pg-no-plugin-10000-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_LIST_RPS_4="$(tail -n +20 pg-no-plugin-10000-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_BASE_LIST_RPS_5="$(tail -n +20 pg-no-plugin-10000-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_NO_PLUGIN_BASE_LIST_1 + $PG_NO_PLUGIN_BASE_LIST_2 + $PG_NO_PLUGIN_BASE_LIST_3 + $PG_NO_PLUGIN_BASE_LIST_4 + $PG_NO_PLUGIN_BASE_LIST_5" | bc -l) + RPS_SUM=$(echo "$PG_NO_PLUGIN_BASE_LIST_RPS_1 + $PG_NO_PLUGIN_BASE_LIST_RPS_2 + $PG_NO_PLUGIN_BASE_LIST_RPS_3 + $PG_NO_PLUGIN_BASE_LIST_RPS_4 + $PG_NO_PLUGIN_BASE_LIST_RPS_5" | bc -l) + COUNT=5 + export PSQL_NO_PLUGIN_BASE_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PSQL_NO_PLUGIN_BASE_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" + echo "PSQL_NO_PLUGIN_BASE_LIST_RESULT=${PSQL_NO_PLUGIN_BASE_LIST_RESULT}" >> $GITHUB_ENV + echo "PSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT=${PSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" >> $GITHUB_ENV + - name: Drop PGSQL ECCUBE for 4.2.1-20230116 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.dev.yml -f docker-compose.pgsql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # MYSQL + # BASE PRODUCTS + # PLUGIN + - name: MYSQL BASE PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download Plugin + uses: actions/checkout@master + with: + path: app/Plugin/TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomerApp42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomerApp42 + - name: Download Plugin TwoFactorAuthCustomerSms42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 + path: app/Plugin/TwoFactorAuthCustomerSms42 + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml up -d + - 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.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 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 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 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 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 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 + - name: Wait for 30 seconds for the database to load, (because MySQL is slow to initialize) + run: sleep 30s + shell: bash + - name: Request home page + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-base-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-base-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-base-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-base-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-base-home_5.txt + export MY_PLUGIN_HOME_BASE_1="$(tail -n +23 mysql-plugin-base-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_BASE_2="$(tail -n +23 mysql-plugin-base-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_BASE_3="$(tail -n +23 mysql-plugin-base-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_BASE_4="$(tail -n +23 mysql-plugin-base-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_BASE_5="$(tail -n +23 mysql-plugin-base-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_BASE_RPS_1="$(tail -n +20 mysql-plugin-base-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_BASE_RPS_2="$(tail -n +20 mysql-plugin-base-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_BASE_RPS_3="$(tail -n +20 mysql-plugin-base-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_BASE_RPS_4="$(tail -n +20 mysql-plugin-base-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_BASE_RPS_5="$(tail -n +20 mysql-plugin-base-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_PLUGIN_HOME_BASE_1 + $MY_PLUGIN_HOME_BASE_2 + $MY_PLUGIN_HOME_BASE_3 + $MY_PLUGIN_HOME_BASE_4 + $MY_PLUGIN_HOME_BASE_5" | bc -l) + RPS_SUM=$(echo "$MY_PLUGIN_HOME_BASE_RPS_1 + $MY_PLUGIN_HOME_BASE_RPS_2 + $MY_PLUGIN_HOME_BASE_RPS_3 + $MY_PLUGIN_HOME_BASE_RPS_4 + $MY_PLUGIN_HOME_BASE_RPS_5" | bc -l) + COUNT=5 + export MSQL_PLUGIN_BASE_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_PLUGIN_BASE_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_PLUGIN_BASE_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_PLUGIN_BASE_HOME_RPS_RESULT}" + echo "MSQL_PLUGIN_BASE_HOME_RESULT=${MSQL_PLUGIN_BASE_HOME_RESULT}" >> $GITHUB_ENV + echo "MSQL_PLUGIN_BASE_HOME_RPS_RESULT=${MSQL_PLUGIN_BASE_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-base-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-base-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-base-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-base-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-base-list_5.txt + export MY_PLUGIN_BASE_LIST_1="$(tail -n +23 mysql-plugin-base-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_BASE_LIST_2="$(tail -n +23 mysql-plugin-base-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_BASE_LIST_3="$(tail -n +23 mysql-plugin-base-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_BASE_LIST_4="$(tail -n +23 mysql-plugin-base-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_BASE_LIST_5="$(tail -n +23 mysql-plugin-base-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_BASE_LIST_RPS_1="$(tail -n +20 mysql-plugin-base-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_BASE_LIST_RPS_2="$(tail -n +20 mysql-plugin-base-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_BASE_LIST_RPS_3="$(tail -n +20 mysql-plugin-base-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_BASE_LIST_RPS_4="$(tail -n +20 mysql-plugin-base-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_BASE_LIST_RPS_5="$(tail -n +20 mysql-plugin-base-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_PLUGIN_BASE_LIST_1 + $MY_PLUGIN_BASE_LIST_2 + $MY_PLUGIN_BASE_LIST_3 + $MY_PLUGIN_BASE_LIST_4 + $MY_PLUGIN_BASE_LIST_5" | bc -l) + RPS_SUM=$(echo "$MY_PLUGIN_BASE_LIST_RPS_1 + $MY_PLUGIN_BASE_LIST_RPS_2 + $MY_PLUGIN_BASE_LIST_RPS_3 + $MY_PLUGIN_BASE_LIST_RPS_4 + $MY_PLUGIN_BASE_LIST_RPS_5" | bc -l) + COUNT=5 + export MSQL_PLUGIN_BASE_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_PLUGIN_BASE_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_PLUGIN_BASE_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_PLUGIN_BASE_LIST_RPS_RESULT}" + echo "MSQL_PLUGIN_BASE_LIST_RESULT=${MSQL_PLUGIN_BASE_LIST_RESULT}" >> $GITHUB_ENV + echo "MSQL_PLUGIN_BASE_LIST_RPS_RESULT=${MSQL_PLUGIN_BASE_LIST_RPS_RESULT}" >> $GITHUB_ENV + - name: Drop MYSQL ECCUBE for 4.2 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # MYSQL + # BASE PRODUCTS + # NO PLUGIN + - name: MYSQL BASE NO PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml up -d + - name: Wait for 30 seconds for the database to load, (because MySQL is slow to initialize) + run: sleep 30s + shell: bash + - name: Request home page + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-base-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-base-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-base-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-base-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-base-home_5.txt + export MY_NO_PLUGIN_HOME_1="$(tail -n +23 mysql-no-plugin-base-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_2="$(tail -n +23 mysql-no-plugin-base-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_3="$(tail -n +23 mysql-no-plugin-base-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_4="$(tail -n +23 mysql-no-plugin-base-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_5="$(tail -n +23 mysql-no-plugin-base-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_RPS_1="$(tail -n +20 mysql-no-plugin-base-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_2="$(tail -n +20 mysql-no-plugin-base-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_3="$(tail -n +20 mysql-no-plugin-base-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_4="$(tail -n +20 mysql-no-plugin-base-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_5="$(tail -n +20 mysql-no-plugin-base-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_NO_PLUGIN_HOME_1 + $MY_NO_PLUGIN_HOME_2 + $MY_NO_PLUGIN_HOME_3 + $MY_NO_PLUGIN_HOME_4 + $MY_NO_PLUGIN_HOME_5" | bc -l) + RPS_SUM=$(echo "$MY_NO_PLUGIN_HOME_RPS_1 + $MY_NO_PLUGIN_HOME_RPS_2 + $MY_NO_PLUGIN_HOME_RPS_3 + $MY_NO_PLUGIN_HOME_RPS_4 + $MY_NO_PLUGIN_HOME_RPS_5" | bc -l) + COUNT=5 + export MSQL_NO_PLUGIN_BASE_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_NO_PLUGIN_BASE_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" + echo "MSQL_NO_PLUGIN_BASE_HOME_RESULT=${MSQL_NO_PLUGIN_BASE_HOME_RESULT}" >> $GITHUB_ENV + echo "MSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT=${MSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-base-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-base-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-base-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-base-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-base-list_5.txt + export MY_NO_PLUGIN_LIST_1="$(tail -n +23 mysql-no-plugin-base-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_2="$(tail -n +23 mysql-no-plugin-base-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_3="$(tail -n +23 mysql-no-plugin-base-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_4="$(tail -n +23 mysql-no-plugin-base-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_5="$(tail -n +23 mysql-no-plugin-base-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_RPS_1="$(tail -n +20 mysql-no-plugin-base-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_2="$(tail -n +20 mysql-no-plugin-base-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_3="$(tail -n +20 mysql-no-plugin-base-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_4="$(tail -n +20 mysql-no-plugin-base-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_5="$(tail -n +20 mysql-no-plugin-base-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_NO_PLUGIN_LIST_1 + $MY_NO_PLUGIN_LIST_2 + $MY_NO_PLUGIN_LIST_3 + $MY_NO_PLUGIN_LIST_4 + $MY_NO_PLUGIN_LIST_5" | bc -l) + RPS_SUM=$(echo "$MY_NO_PLUGIN_LIST_RPS_1 + $MY_NO_PLUGIN_LIST_RPS_2 + $MY_NO_PLUGIN_LIST_RPS_3 + $MY_NO_PLUGIN_LIST_RPS_4 + $MY_NO_PLUGIN_LIST_RPS_5" | bc -l) + COUNT=5 + export MSQL_NO_PLUGIN_BASE_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_NO_PLUGIN_BASE_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" + echo "MSQL_NO_PLUGIN_BASE_LIST_RESULT=${MSQL_NO_PLUGIN_BASE_LIST_RESULT}" >> $GITHUB_ENV + echo "MSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT=${MSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" >> $GITHUB_ENV + - name: Drop MYSQL ECCUBE + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.mysql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # POSTGRES SQL + # 10,000 PRODUCTS + # PLUGIN + - name: PSQL 10000 PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download 4.2 Apache Bench Data + run: | + mkdir .github/workflows/pgsql + sudo chmod 777 .github/workflows/pgsql + curl --fail -LJO https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/docker-compose.bench.pgsql.yml + if [ ! -f docker-compose.bench.pgsql.yml ]; then + echo "docker-compose.bench.pgsql.yml File not found!" + else + echo "docker-compose.bench.pgsql.yml File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/.github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql -o .github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql + if [ ! -f .github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql ]; then + echo ".github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql File not found!" + else + echo ".github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/.github/workflows/pgsql/Dockerfile -o .github/workflows/pgsql/Dockerfile + if [ ! -f .github/workflows/pgsql/Dockerfile ]; then + echo ".github/workflows/pgsql/Dockerfile File not found!" + else + echo ".github/workflows/pgsql/Dockerfile File found!" + fi + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml up -d + - name: Download Plugin + uses: actions/checkout@master + with: + path: app/Plugin/TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomerApp42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomerApp42 + - name: Download Plugin TwoFactorAuthCustomerSms42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 + path: app/Plugin/TwoFactorAuthCustomerSms42 + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml up -d + - name: Wait 2 minutes for the database to load, (as I do not know the databases active state) + run: sleep 120s + 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 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 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 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 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 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 + - name: Request home page - PGSQL PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-10000-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-10000-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-10000-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-10000-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-plugin-10000-home_5.txt + export PG_PLUGIN_10000_HOME_1="$(tail -n +23 pg-plugin-10000-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_HOME_2="$(tail -n +23 pg-plugin-10000-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_HOME_3="$(tail -n +23 pg-plugin-10000-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_HOME_4="$(tail -n +23 pg-plugin-10000-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_HOME_5="$(tail -n +23 pg-plugin-10000-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_HOME_RPS_1="$(tail -n +20 pg-plugin-10000-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_HOME_RPS_2="$(tail -n +20 pg-plugin-10000-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_HOME_RPS_3="$(tail -n +20 pg-plugin-10000-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_HOME_RPS_4="$(tail -n +20 pg-plugin-10000-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_HOME_RPS_5="$(tail -n +20 pg-plugin-10000-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_PLUGIN_10000_HOME_1 + $PG_PLUGIN_10000_HOME_2 + $PG_PLUGIN_10000_HOME_3 + $PG_PLUGIN_10000_HOME_4 + $PG_PLUGIN_10000_HOME_5" | bc -l) + RPS_SUM=$(echo "$PG_PLUGIN_10000_HOME_RPS_1 + $PG_PLUGIN_10000_HOME_RPS_2 + $PG_PLUGIN_10000_HOME_RPS_3 + $PG_PLUGIN_10000_HOME_RPS_4 + $PG_PLUGIN_10000_HOME_RPS_5" | bc -l) + COUNT=5 + export PG_PLUGIN_10000_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PG_PLUGIN_10000_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PG_PLUGIN_10000_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PG_PLUGIN_10000_HOME_RPS_RESULT}" + echo "PG_PLUGIN_10000_HOME_RESULT=${PG_PLUGIN_10000_HOME_RESULT}" >> $GITHUB_ENV + echo "PG_PLUGIN_10000_HOME_RPS_RESULT=${PG_PLUGIN_10000_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - PGSQL PLUGIN 10000 PRODUCTS + run: | + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-10000-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-10000-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-10000-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-10000-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-plugin-10000-list_5.txt + export PG_PLUGIN_10000_LIST1="$(tail -n +23 pg-plugin-10000-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_LIST2="$(tail -n +23 pg-plugin-10000-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_LIST3="$(tail -n +23 pg-plugin-10000-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_LIST4="$(tail -n +23 pg-plugin-10000-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_LIST5="$(tail -n +23 pg-plugin-10000-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_PLUGIN_10000_LISTRPS_1="$(tail -n +20 pg-plugin-10000-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_LISTRPS_2="$(tail -n +20 pg-plugin-10000-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_LISTRPS_3="$(tail -n +20 pg-plugin-10000-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_LISTRPS_4="$(tail -n +20 pg-plugin-10000-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_PLUGIN_10000_LISTRPS_5="$(tail -n +20 pg-plugin-10000-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_PLUGIN_10000_LIST1 + $PG_PLUGIN_10000_LIST2 + $PG_PLUGIN_10000_LIST3 + $PG_PLUGIN_10000_LIST4 + $PG_PLUGIN_10000_LIST5" | bc -l) + RPS_SUM=$(echo "$PG_PLUGIN_10000_LISTRPS_1 + $PG_PLUGIN_10000_LISTRPS_2 + $PG_PLUGIN_10000_LISTRPS_3 + $PG_PLUGIN_10000_LISTRPS_4 + $PG_PLUGIN_10000_LISTRPS_5" | bc -l) + COUNT=5 + export PG_PLUGIN_10000_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PG_PLUGIN_10000_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PG_PLUGIN_10000_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PG_PLUGIN_10000_LIST_RPS_RESULT}" + echo "PG_PLUGIN_10000_LIST_RESULT=${PG_PLUGIN_10000_LIST_RESULT}" >> $GITHUB_ENV + echo "PG_PLUGIN_10000_LIST_RPS_RESULT=${PG_PLUGIN_10000_LIST_RPS_RESULT}" >> $GITHUB_ENV + # Upload Evidence + - name: Print Average Results to CSV + run: | + echo "POSTGRES PLUGIN 100000 _ ${PG_PLUGIN_10000_HOME_RESULT}, ${PG_PLUGIN_10000_HOME_RPS_RESULT}, ${PG_PLUGIN_10000_LIST_RESULT}, ${PG_PLUGIN_10000_LIST_RPS_RESULT}" + - name: Drop PGSQL ECCUBE + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # POSTGRES SQL + # 10,000 PRODUCTS + # NO PLUGIN + - name: PSQL 10000 NO PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download 4.2 Apache Bench Data + run: | + mkdir .github/workflows/pgsql + sudo chmod 777 .github/workflows/pgsql + curl --fail -LJO https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/docker-compose.bench.pgsql.yml + if [ ! -f docker-compose.bench.pgsql.yml ]; then + echo "docker-compose.bench.pgsql.yml File not found!" + else + echo "docker-compose.bench.pgsql.yml File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/.github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql -o .github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql + if [ ! -f .github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql ]; then + echo ".github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql File not found!" + else + echo ".github/workflows/pgsql/eccubedb_localhost-2022_06_30_17_25_15-dump.sql File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/apache_workbench_speed_tool/.github/workflows/pgsql/Dockerfile -o .github/workflows/pgsql/Dockerfile + if [ ! -f .github/workflows/pgsql/Dockerfile ]; then + echo ".github/workflows/pgsql/Dockerfile File not found!" + else + echo ".github/workflows/pgsql/Dockerfile File found!" + fi + - name: Start Load EC-CUBE on 4.2.1-20230116 + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml up -d + - name: Wait 2 minutes for the database to load, (as I do not know the databases active state) + run: sleep 60s + shell: bash + - name: Request home page - PGSQL PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > pg-no-plugin-10000-home_5.txt + export PG_NO_PLUGIN_10000_HOME_1="$(tail -n +23 pg-no-plugin-10000-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_HOME_2="$(tail -n +23 pg-no-plugin-10000-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_HOME_3="$(tail -n +23 pg-no-plugin-10000-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_HOME_4="$(tail -n +23 pg-no-plugin-10000-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_HOME_5="$(tail -n +23 pg-no-plugin-10000-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_HOME_RPS_1="$(tail -n +20 pg-no-plugin-10000-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_HOME_RPS_2="$(tail -n +20 pg-no-plugin-10000-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_HOME_RPS_3="$(tail -n +20 pg-no-plugin-10000-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_HOME_RPS_4="$(tail -n +20 pg-no-plugin-10000-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_HOME_RPS_5="$(tail -n +20 pg-no-plugin-10000-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_NO_PLUGIN_10000_HOME_1 + $PG_NO_PLUGIN_10000_HOME_2 + $PG_NO_PLUGIN_10000_HOME_3 + $PG_NO_PLUGIN_10000_HOME_4 + $PG_NO_PLUGIN_10000_HOME_5" | bc -l) + RPS_SUM=$(echo "$PG_NO_PLUGIN_10000_HOME_RPS_1 + $PG_NO_PLUGIN_10000_HOME_RPS_2 + $PG_NO_PLUGIN_10000_HOME_RPS_3 + $PG_NO_PLUGIN_10000_HOME_RPS_4 + $PG_NO_PLUGIN_10000_HOME_RPS_5" | bc -l) + COUNT=5 + export PG_NO_PLUGIN_10000_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PG_NO_PLUGIN_10000_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PG_NO_PLUGIN_10000_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PG_NO_PLUGIN_10000_HOME_RPS_RESULT}" + echo "PG_NO_PLUGIN_10000_HOME_RESULT=${PG_NO_PLUGIN_10000_HOME_RESULT}" >> $GITHUB_ENV + echo "PG_NO_PLUGIN_10000_HOME_RPS_RESULT=${PG_NO_PLUGIN_10000_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - PGSQL PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > pg-no-plugin-10000-list_5.txt + export PG_NO_PLUGIN_10000_LIST_1="$(tail -n +23 pg-no-plugin-10000-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_LIST_2="$(tail -n +23 pg-no-plugin-10000-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_LIST_3="$(tail -n +23 pg-no-plugin-10000-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_LIST_4="$(tail -n +23 pg-no-plugin-10000-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_LIST_5="$(tail -n +23 pg-no-plugin-10000-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export PG_NO_PLUGIN_10000_LIST_RPS_1="$(tail -n +20 pg-no-plugin-10000-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_LIST_RPS_2="$(tail -n +20 pg-no-plugin-10000-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_LIST_RPS_3="$(tail -n +20 pg-no-plugin-10000-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_LIST_RPS_4="$(tail -n +20 pg-no-plugin-10000-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export PG_NO_PLUGIN_10000_LIST_RPS_5="$(tail -n +20 pg-no-plugin-10000-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$PG_NO_PLUGIN_10000_LIST_1 + $PG_NO_PLUGIN_10000_LIST_2 + $PG_NO_PLUGIN_10000_LIST_3 + $PG_NO_PLUGIN_10000_LIST_4 + $PG_NO_PLUGIN_10000_LIST_5" | bc -l) + RPS_SUM=$(echo "$PG_NO_PLUGIN_10000_LIST_RPS_1 + $PG_NO_PLUGIN_10000_LIST_RPS_2 + $PG_NO_PLUGIN_10000_LIST_RPS_3 + $PG_NO_PLUGIN_10000_LIST_RPS_4 + $PG_NO_PLUGIN_10000_LIST_RPS_5" | bc -l) + COUNT=5 + export PG_NO_PLUGIN_10000_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export PG_NO_PLUGIN_10000_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${PG_NO_PLUGIN_10000_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${PG_NO_PLUGIN_10000_LIST_RPS_RESULT}" + echo "PG_NO_PLUGIN_10000_LIST_RESULT=${PG_NO_PLUGIN_10000_LIST_RESULT}" >> $GITHUB_ENV + echo "PG_NO_PLUGIN_10000_LIST_RPS_RESULT=${PG_NO_PLUGIN_10000_LIST_RPS_RESULT}" >> $GITHUB_ENV + # Upload Evidence + - name: Print 4.2.1-20230116 Average Results to Screen + run: | + echo "4.2 POSTGRES 100000 _ ${PG_NO_PLUGIN_10000_HOME_RESULT}, ${PG_NO_PLUGIN_10000_HOME_RPS_RESULT}, ${PG_NO_PLUGIN_10000_LIST_RESULT}, ${PG_NO_PLUGIN_10000_LIST_RPS_RESULT}" + - name: Drop PGSQL ECCUBE for 4.2.1-20230116 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.pgsql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # MYSQL SQL + # 10,000 PRODUCTS + # PLUGIN + - name: MYSQL 10000 PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download 4.2 Apache Bench Data + run: | + mkdir .github/workflows/mysql + sudo chmod 777 .github/workflows/mysql + curl --fail -LJO https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/docker-compose.bench.mysql.yml + if [ ! -f docker-compose.bench.mysql.yml ]; then + echo "docker-compose.bench.mysql.yml File not found!" + else + echo "docker-compose.bench.mysql.yml File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/.github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql -o .github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql + if [ ! -f .github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql ]; then + echo ".github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql File not found!" + else + echo ".github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/.github/workflows/mysql/Dockerfile -o .github/workflows/mysql/Dockerfile + if [ ! -f .github/workflows/mysql/Dockerfile ]; then + echo ".github/workflows/mysql/Dockerfile File not found!" + else + echo ".github/workflows/mysql/Dockerfile File found!" + fi + - name: Download Plugin + uses: actions/checkout@master + with: + path: app/Plugin/TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomerApp42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomerApp42 + - name: Download Plugin TwoFactorAuthCustomerSms42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 + path: app/Plugin/TwoFactorAuthCustomerSms42 + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml up -d + - name: Sleep for MySQL + run: sleep 120s + shell: bash + - name: Enquire ECCUBE + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml ps + - name: Get MYSQL Logs + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs mysql + - name: Get ECCUBE Logs + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs ec-cube + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml up -d + - name: Enquire ECCUBE + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml ps + - name: Get MYSQL Logs + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs mysql + - name: Get ECCUBE Logs + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs ec-cube + - name: Sleep for MySQL + run: sleep 60s + shell: bash + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml up -d + - name: Enquire ECCUBE + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml ps + - name: Get MYSQL Logs + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml logs mysql + - name: Get ECCUBE Logs + run: | + 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 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 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 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 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 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 + - 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 + - name: Sleep for MySQL + run: sleep 30s + shell: bash + - name: Request home page - MYSQL PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-10000-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-10000-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-10000-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-10000-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-plugin-10000-home_5.txt + export MY_PLUGIN_HOME_10000_1="$(tail -n +23 mysql-plugin-10000-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_10000_2="$(tail -n +23 mysql-plugin-10000-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_10000_3="$(tail -n +23 mysql-plugin-10000-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_10000_4="$(tail -n +23 mysql-plugin-10000-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_10000_5="$(tail -n +23 mysql-plugin-10000-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_HOME_10000_RPS_1="$(tail -n +20 mysql-plugin-10000-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_10000_RPS_2="$(tail -n +20 mysql-plugin-10000-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_10000_RPS_3="$(tail -n +20 mysql-plugin-10000-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_10000_RPS_4="$(tail -n +20 mysql-plugin-10000-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_HOME_10000_RPS_5="$(tail -n +20 mysql-plugin-10000-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_PLUGIN_HOME_10000_1 + $MY_PLUGIN_HOME_10000_2 + $MY_PLUGIN_HOME_10000_3 + $MY_PLUGIN_HOME_10000_4 + $MY_PLUGIN_HOME_10000_5" | bc -l) + RPS_SUM=$(echo "$MY_PLUGIN_HOME_10000_RPS_1 + $MY_PLUGIN_HOME_10000_RPS_2 + $MY_PLUGIN_HOME_10000_RPS_3 + $MY_PLUGIN_HOME_10000_RPS_4 + $MY_PLUGIN_HOME_10000_RPS_5" | bc -l) + COUNT=5 + export MSQL_PLUGIN_10000_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_PLUGIN_10000_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_PLUGIN_10000_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_PLUGIN_10000_HOME_RPS_RESULT}" + echo "MSQL_PLUGIN_10000_HOME_RESULT=${MSQL_PLUGIN_10000_HOME_RESULT}" >> $GITHUB_ENV + echo "MSQL_PLUGIN_10000_HOME_RPS_RESULT=${MSQL_PLUGIN_10000_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - MYSQL PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-10000-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-10000-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-10000-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-10000-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-plugin-10000-list_5.txt + export MY_PLUGIN_10000_LIST_1="$(tail -n +23 mysql-plugin-10000-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_10000_LIST_2="$(tail -n +23 mysql-plugin-10000-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_10000_LIST_3="$(tail -n +23 mysql-plugin-10000-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_10000_LIST_4="$(tail -n +23 mysql-plugin-10000-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_10000_LIST_5="$(tail -n +23 mysql-plugin-10000-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_PLUGIN_10000_LIST_RPS_1="$(tail -n +20 mysql-plugin-10000-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_10000_LIST_RPS_2="$(tail -n +20 mysql-plugin-10000-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_10000_LIST_RPS_3="$(tail -n +20 mysql-plugin-10000-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_10000_LIST_RPS_4="$(tail -n +20 mysql-plugin-10000-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_PLUGIN_10000_LIST_RPS_5="$(tail -n +20 mysql-plugin-10000-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_PLUGIN_10000_LIST_1 + $MY_PLUGIN_10000_LIST_2 + $MY_PLUGIN_10000_LIST_3 + $MY_PLUGIN_10000_LIST_4 + $MY_PLUGIN_10000_LIST_5" | bc -l) + RPS_SUM=$(echo "$MY_PLUGIN_10000_LIST_RPS_1 + $MY_PLUGIN_10000_LIST_RPS_2 + $MY_PLUGIN_10000_LIST_RPS_3 + $MY_PLUGIN_10000_LIST_RPS_4 + $MY_PLUGIN_10000_LIST_RPS_5" | bc -l) + COUNT=5 + export MSQL_PLUGIN_10000_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_PLUGIN_10000_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_PLUGIN_10000_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_PLUGIN_10000_LIST_RPS_RESULT}" + echo "MSQL_PLUGIN_10000_LIST_RESULT=${MSQL_PLUGIN_10000_LIST_RESULT}" >> $GITHUB_ENV + echo "MSQL_PLUGIN_10000_LIST_RPS_RESULT=${MSQL_PLUGIN_10000_LIST_RPS_RESULT}" >> $GITHUB_ENV + - name: Drop MYSQL ECCUBE for 4.2 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + # MYSQL SQL + # 10,000 PRODUCTS + # NO PLUGIN + - name: MYSQL 10000 NO PLUGIN + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + - name: Force open permissions + run: | + sudo chmod 777 -R . + - name: Download 4.2 Apache Bench Data + run: | + mkdir .github/workflows/mysql + sudo chmod 777 .github/workflows/mysql + curl --fail -LJO https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/docker-compose.bench.mysql.yml + if [ ! -f docker-compose.bench.mysql.yml ]; then + echo "docker-compose.bench.mysql.yml File not found!" + else + echo "docker-compose.bench.mysql.yml File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/.github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql -o .github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql + if [ ! -f .github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql ]; then + echo ".github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql File not found!" + else + echo ".github/workflows/mysql/mysql_localhost-2022_07_06_19_15_00-dump.sql File found!" + fi + curl --fail -LJ https://raw.githubusercontent.com/${{ github.repository_owner }}/ec-cube/feature/ab_testing/.github/workflows/mysql/Dockerfile -o .github/workflows/mysql/Dockerfile + if [ ! -f .github/workflows/mysql/Dockerfile ]; then + echo ".github/workflows/mysql/Dockerfile File not found!" + else + echo ".github/workflows/mysql/Dockerfile File found!" + fi + - name: Start Load EC-CUBE + run: | + sed -i 's!APP_ENV: "dev"!APP_ENV: "prod"!g' docker-compose.yml + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml up -d + - name: Sleep for MySQL + run: sleep 120s + shell: bash + - 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 + - name: Sleep for MySQL + run: sleep 30s + shell: bash + - name: Request home page - MYSQL NO PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-10000-home_1.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-10000-home_2.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-10000-home_3.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-10000-home_4.txt + ab -n 100 -c 10 -l http://localhost:8080/ > mysql-no-plugin-10000-home_5.txt + export MY_NO_PLUGIN_HOME_1="$(tail -n +23 mysql-no-plugin-10000-home_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_2="$(tail -n +23 mysql-no-plugin-10000-home_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_3="$(tail -n +23 mysql-no-plugin-10000-home_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_4="$(tail -n +23 mysql-no-plugin-10000-home_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_5="$(tail -n +23 mysql-no-plugin-10000-home_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_HOME_RPS_1="$(tail -n +20 mysql-no-plugin-10000-home_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_2="$(tail -n +20 mysql-no-plugin-10000-home_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_3="$(tail -n +20 mysql-no-plugin-10000-home_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_4="$(tail -n +20 mysql-no-plugin-10000-home_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_HOME_RPS_5="$(tail -n +20 mysql-no-plugin-10000-home_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_NO_PLUGIN_HOME_1 + $MY_NO_PLUGIN_HOME_2 + $MY_NO_PLUGIN_HOME_3 + $MY_NO_PLUGIN_HOME_4 + $MY_NO_PLUGIN_HOME_5" | bc -l) + RPS_SUM=$(echo "$MY_NO_PLUGIN_HOME_RPS_1 + $MY_NO_PLUGIN_HOME_RPS_2 + $MY_NO_PLUGIN_HOME_RPS_3 + $MY_NO_PLUGIN_HOME_RPS_4 + $MY_NO_PLUGIN_HOME_RPS_5" | bc -l) + COUNT=5 + export MSQL_NO_PLUGIN_10000_HOME_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_NO_PLUGIN_10000_HOME_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_NO_PLUGIN_10000_HOME_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_NO_PLUGIN_10000_HOME_RPS_RESULT}" + echo "MSQL_NO_PLUGIN_10000_HOME_RESULT=${MSQL_NO_PLUGIN_10000_HOME_RESULT}" >> $GITHUB_ENV + echo "MSQL_NO_PLUGIN_10000_HOME_RPS_RESULT=${MSQL_NO_PLUGIN_10000_HOME_RPS_RESULT}" >> $GITHUB_ENV + - name: Request list page - MYSQL NO PLUGIN 10000 PRODUCTS + run: | + sudo apt-get install apache2-utils + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-10000-list_1.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-10000-list_2.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-10000-list_3.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-10000-list_4.txt + ab -n 100 -c 10 -l http://localhost:8080/products/list > mysql-no-plugin-10000-list_5.txt + export MY_NO_PLUGIN_LIST_1="$(tail -n +23 mysql-no-plugin-10000-list_1.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_2="$(tail -n +23 mysql-no-plugin-10000-list_2.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_3="$(tail -n +23 mysql-no-plugin-10000-list_3.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_4="$(tail -n +23 mysql-no-plugin-10000-list_4.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_5="$(tail -n +23 mysql-no-plugin-10000-list_5.txt | grep -o -P '(?<=:).*(?=\[ms\])')" + export MY_NO_PLUGIN_LIST_RPS_1="$(tail -n +20 mysql-no-plugin-10000-list_1.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_2="$(tail -n +20 mysql-no-plugin-10000-list_2.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_3="$(tail -n +20 mysql-no-plugin-10000-list_3.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_4="$(tail -n +20 mysql-no-plugin-10000-list_4.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + export MY_NO_PLUGIN_LIST_RPS_5="$(tail -n +20 mysql-no-plugin-10000-list_5.txt | grep -o -P '(?<=Requests per second:).*(?=\[#/sec\])')" + SUM=$(echo "$MY_NO_PLUGIN_LIST_1 + $MY_NO_PLUGIN_LIST_2 + $MY_NO_PLUGIN_LIST_3 + $MY_NO_PLUGIN_LIST_4 + $MY_NO_PLUGIN_LIST_5" | bc -l) + RPS_SUM=$(echo "$MY_NO_PLUGIN_LIST_RPS_1 + $MY_NO_PLUGIN_LIST_RPS_2 + $MY_NO_PLUGIN_LIST_RPS_3 + $MY_NO_PLUGIN_LIST_RPS_4 + $MY_NO_PLUGIN_LIST_RPS_5" | bc -l) + COUNT=5 + export MSQL_NO_PLUGIN_10000_LIST_RESULT=$(echo "scale=4; 1.0 * $SUM / $COUNT" | bc -l) + export MSQL_NO_PLUGIN_10000_LIST_RPS_RESULT=$(echo "scale=4; 1.0 * $RPS_SUM / $COUNT" | bc -l) + echo "TIME PER REQUEST AVG: ${MSQL_NO_PLUGIN_10000_LIST_RESULT}" + echo "REQUESTS PER SECOND AVG: ${MSQL_NO_PLUGIN_10000_LIST_RPS_RESULT}" + echo "MSQL_NO_PLUGIN_10000_LIST_RESULT=${MSQL_NO_PLUGIN_10000_LIST_RESULT}" >> $GITHUB_ENV + echo "MSQL_NO_PLUGIN_10000_LIST_RPS_RESULT=${MSQL_NO_PLUGIN_10000_LIST_RPS_RESULT}" >> $GITHUB_ENV + - name: Drop MYSQL ECCUBE for 4.2.1-20230116 + run: | + docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f docker-compose.bench.mysql.yml down -v + - name: 'Cleanup build folder' + run: | + sudo ls -la ./ + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + sudo ls -la ./ + - name: Bundle All Average Results to CSV + run: | + echo "Pattern, DB, Page, PLUGIN - TIME PER REQUEST, NO PLUGIN - TIME PER REQUEST, PLUGIN - REQUESTS PER SECOND,NO PLUGIN - REQUESTS PER SECOND" >> total.csv + echo "Base Install Result, PGSQL, TOP, ${PSQL_PLUGIN_BASE_HOME_RESULT}, ${PSQL_NO_PLUGIN_BASE_HOME_RESULT}, ${PSQL_PLUGIN_BASE_HOME_RPS_RESULT}, ${PSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" >> total.csv + echo "Base Install Result, PGSQL, LIST, ${PSQL_PLUGIN_BASE_LIST_RESULT}, ${PSQL_NO_PLUGIN_BASE_LIST_RESULT}, ${PSQL_PLUGIN_BASE_LIST_RPS_RESULT}, ${PSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" >> total.csv + echo "Base Install Result, MYSQL, TOP, ${MSQL_PLUGIN_BASE_HOME_RESULT}, ${MSQL_NO_PLUGIN_BASE_HOME_RESULT}, ${MSQL_PLUGIN_BASE_HOME_RPS_RESULT}, ${MSQL_NO_PLUGIN_BASE_HOME_RPS_RESULT}" >> total.csv + echo "Base Install Result, MYSQL, LIST, $MSQL_PLUGIN_BASE_LIST_RESULT, ${MSQL_NO_PLUGIN_BASE_LIST_RESULT}, ${MSQL_PLUGIN_BASE_LIST_RPS_RESULT}, ${MSQL_NO_PLUGIN_BASE_LIST_RPS_RESULT}" >> total.csv + echo "10000 Product Result, PGSQL, TOP, ${PG_PLUGIN_10000_HOME_RESULT}, ${PG_NO_PLUGIN_10000_HOME_RESULT}, ${PG_PLUGIN_10000_HOME_RPS_RESULT}, ${PG_NO_PLUGIN_10000_HOME_RPS_RESULT}" >> total.csv + echo "10000 Product Result, PGSQL, LIST, ${PG_PLUGIN_10000_LIST_RESULT}, ${PG_NO_PLUGIN_10000_LIST_RESULT}, ${PG_PLUGIN_10000_LIST_RPS_RESULT}, ${PG_NO_PLUGIN_10000_LIST_RPS_RESULT}" >> total.csv + echo "10000 Product Result, MYSQL, TOP, ${MSQL_PLUGIN_10000_HOME_RESULT}, ${MSQL_NO_PLUGIN_10000_HOME_RESULT}, ${MSQL_PLUGIN_10000_HOME_RPS_RESULT}, ${MSQL_NO_PLUGIN_10000_HOME_RPS_RESULT}" >> total.csv + echo "10000 Product Result, MYSQL, LIST, ${MSQL_PLUGIN_10000_LIST_RESULT}, ${MSQL_NO_PLUGIN_10000_LIST_RESULT}, ${MSQL_PLUGIN_10000_LIST_RPS_RESULT}, ${MSQL_NO_PLUGIN_10000_LIST_RPS_RESULT}" >> total.csv + # Upload Evidence + ## FINALISE + - name: Upload complete evidence (ALL) + if: always() + uses: actions/upload-artifact@v2 + with: + name: ab-${{ env.ARTIFACT_NAME }}-complete + path: total.csv diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml new file mode 100644 index 0000000..d57a645 --- /dev/null +++ b/.github/workflows/e2e-testing.yml @@ -0,0 +1,180 @@ +name: E2E test for EC-CUBE +on: + workflow_dispatch: + +jobs: + codeception: + name: Codeception + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + php: [ 8.0 ] + db: [ pgsql ] + group: [ 'admin01', 'admin02', 'admin03', 'front', 'restrict-fileupload', 'installer' ] + include: + - db: pgsql + database_url: postgres://postgres:password@127.0.0.1:5432/eccube_db + database_server_version: 14 + - group: 'admin01' + app_env: 'codeception' + - group: 'admin02' + app_env: 'codeception' + - group: 'admin03' + app_env: 'codeception' + - group: 'front' + app_env: 'codeception' + - group: 'restrict-fileupload' + app_env: 'codeception' + - group: 'installer' + app_env: 'install' + services: + postgres: + image: postgres:14 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + mailcatcher: + image: schickling/mailcatcher + ports: + - 1080:1080 + - 1025:1025 + + steps: + - name: Checkout 4.2 Branch (POSTGRES) + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/ec-cube + ref: "4.2" + + - name: Setup PHP + uses: nanasess/setup-php@master + with: + php-version: ${{ matrix.php }} + + - name: Initialize Composer + uses: ./.github/actions/composer + + - name: Setup to EC-CUBE + env: + APP_ENV: ${{ matrix.app_env }} + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + run: | + echo "APP_ENV=${APP_ENV}" > .env + echo "TRUSTED_HOSTS=127.0.0.1,localhost" >> .env + 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 + uses: actions/checkout@master + with: + path: app/Plugin/TwoFactorAuthCustomer42 + - name: Download Plugin TwoFactorAuthCustomerApp42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerApp42 + path: app/Plugin/TwoFactorAuthCustomerApp42 + - name: Download Plugin TwoFactorAuthCustomerSms42 + uses: actions/checkout@master + with: + repository: ${{ github.repository_owner }}/TwoFactorAuthCustomerSms42 + path: app/Plugin/TwoFactorAuthCustomerSms42 + - 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 cache:clear + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomer42 + bin/console cache:clear + + bin/console eccube:plugin:install --code=TwoFactorAuthCustomerApp42 + bin/console cache:clear + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerApp42 + bin/console cache:clear + + bin/console eccube:plugin:install --code=TwoFactorAuthCustomerSms42 + bin/console cache:clear + bin/console eccube:plugin:enable --code=TwoFactorAuthCustomerSms42 + + - name: setup-chromedriver + uses: nanasess/setup-chromedriver@master + + - name: Run chromedriver + run: | + export DISPLAY=:99 + chromedriver --url-base=/wd/hub & + echo ">>> Started chrome-driver" + sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & + echo ">>> Started xvfb" + - name: Run package-api + run: | + if [[ ! -d ${PWD}/repos ]]; then mkdir -p ${PWD}/repos ; fi + docker run -d --rm -v ${PWD}/repos:/repos -e MOCK_REPO_DIR=/repos -p 8080:8080 eccube/mock-package-api:composer2 + cp codeception/_data/plugins/*-1.0.0.tgz repos + - name: Start PHP Development Server + if: ${{ matrix.group != 'restrict-fileupload' }} + env: + APP_ENV: 'codeception' + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + MAILER_DSN: 'smtp://127.0.0.1:1025' + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + run: php -S 127.0.0.1:8000 codeception/router.php & + + - name: Start PHP Development Server + if: ${{ matrix.group == 'restrict-fileupload' }} + env: + APP_ENV: 'codeception' + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + MAILER_DSN: 'smtp://127.0.0.1:1025' + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + ECCUBE_RESTRICT_FILE_UPLOAD: '1' + run: php -S 127.0.0.1:8000 codeception/router.php & + + - name: Codeception + if: ${{ matrix.group != 'restrict-fileupload' }} + env: + APP_ENV: ${{ matrix.app_env }} + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + MAILER_DSN: 'smtp://127.0.0.1:1025' + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + GROUP: ${{ matrix.group }} + SYMFONY_DEPRECATIONS_HELPER: weak + run: vendor/bin/codecept -vvv run acceptance --env chrome,github_action -g ${GROUP} --skip-group restrict-file-upload --html report.html + + - name: Codeception with Restrict file upload + if: ${{ matrix.group == 'restrict-fileupload' }} + env: + APP_ENV: ${{ matrix.app_env }} + DATABASE_URL: ${{ matrix.database_url }} + DATABASE_SERVER_VERSION: ${{ matrix.database_server_version }} + MAILER_DSN: 'smtp://127.0.0.1:1025' + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + GROUP: ${{ matrix.group }} + SYMFONY_DEPRECATIONS_HELPER: weak + ECCUBE_RESTRICT_FILE_UPLOAD: '1' + run: vendor/bin/codecept -vvv run acceptance --env chrome,github_action -g ${GROUP} --html report.html + + - name: Upload evidence + if: failure() + uses: actions/upload-artifact@v2 + with: + name: codeception-${{ matrix.group }}-evidence + path: codeception/_output/ + - name: Upload logs + if: failure() + uses: actions/upload-artifact@v2 + with: + name: codeception-${{ matrix.group }}-logs + path: var/log/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..4227cd3 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,175 @@ +name: CI for TwoFactorAuthCustomer42 +on: + push: + branches: + - '*' + tags: + - '*' + paths: + - '**' + - '!*.md' + pull_request: + branches: + - '*' + paths: + - '**' + - '!*.md' +jobs: + run-on-linux: + name: Run on Linux + runs-on: ubuntu-22.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' ] + 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 + database_charset: utf8mb4 + - db: pgsql + 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: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: ${{ matrix.dbname }} + ports: + - 3308:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + postgres: + image: postgres:14 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: ${{ matrix.dbname }} + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + mailcatcher: + image: schickling/mailcatcher + ports: + - 1080:1080 + - 1025:1025 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: nanasess/setup-php@master + with: + php-version: ${{ matrix.php }} + + - name: Archive Plugin + env: + 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 + with: + repository: 'EC-CUBE/ec-cube' + ref: ${{ matrix.eccube_version }} + path: 'ec-cube' + + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "::set-output name=dir::$(composer config cache-files-dir)" + - uses: actions/cache@v1 + 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 + + - name: Setup EC-CUBE + env: + APP_ENV: 'test' + APP_DEBUG: 0 + 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 + bin/console doctrine:schema:create + bin/console eccube:fixtures:load + - name: Setup Plugin + 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 }} + 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:enable --code=${PLUGIN_CODE} + - name: Disable Plugin + working-directory: 'ec-cube' + 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 }} + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + run: bin/console eccube:plugin:disable --code=${PLUGIN_CODE} + + - name: Uninstall Plugin + 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 }} + ECCUBE_PACKAGE_API_URL: 'http://127.0.0.1:8080' + working-directory: 'ec-cube' + run: bin/console eccube:plugin:uninstall --code=${PLUGIN_CODE} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9a4b67a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: Packaging for EC-CUBE Plugin +on: + release: + types: [ published ] +jobs: + deploy: + name: Build + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Packaging + working-directory: ../ + run: | + rm -rf $GITHUB_WORKSPACE/.github + rm -rf $GITHUB_WORKSPACE/doc + 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 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ runner.workspace }}/${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz + asset_name: ${{ github.event.repository.name }}-${{ github.event.release.tag_name }}.tar.gz + tag: ${{ github.ref }} + overwrite: true diff --git a/Controller/Admin/ConfigController.php b/Controller/Admin/ConfigController.php index 0a9d1a3..37a266f 100644 --- a/Controller/Admin/ConfigController.php +++ b/Controller/Admin/ConfigController.php @@ -13,24 +13,19 @@ namespace Plugin\TwoFactorAuthCustomer42\Controller\Admin; -use Eccube\Repository\BaseInfoRepository; use Eccube\Controller\AbstractController; use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthConfigType; use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Annotation\Route; /** * Class SmsController */ class ConfigController extends AbstractController { - /** - * @var BaseInfoRepository - */ - protected $baseInfoRepository; - /** * @var TwoFactorAuthConfigRepository */ @@ -38,26 +33,30 @@ class ConfigController extends AbstractController /** * ConfigController constructor. - * */ - public function __construct(BaseInfoRepository $baseInfoRepository, TwoFactorAuthConfigRepository $smsConfigRepository) + public function __construct(TwoFactorAuthConfigRepository $smsConfigRepository) { - $this->baseInfoRepository = $baseInfoRepository; $this->smsConfigRepository = $smsConfigRepository; } /** - * @Route("/%eccube_admin_route%/two_factor_auth_customer42/config", name="two_factor_auth_customer42_admin_config") + * @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 array + * @return RedirectResponse|array */ - public function index(Request $request) + public function index(Request $request) { // 設定情報、フォーム情報を取得 $SmsConfig = $this->smsConfigRepository->findOne(); + // APIの秘密キーが設定されている場合、マスキングする + if (!empty($SmsConfig->getApiSecret())) { + // APIの秘密キーをマスキングできるため、デフォルト値を設定 + $SmsConfig->setPlainApiSecret($this->eccubeConfig['eccube_default_password']); + } + $form = $this->createForm(TwoFactorAuthConfigType::class, $SmsConfig); $form->handleRequest($request); @@ -66,6 +65,11 @@ public function index(Request $request) // フォームの入力データを取得 $SmsConfig = $form->getData(); + // APIの秘密キーが変更されていたら、APIの秘密キーを保存する + if ($SmsConfig->getPlainApiSecret() !== $this->eccubeConfig['eccube_default_password']) { + $SmsConfig->setApiSecret($SmsConfig->getPlainApiSecret()); + } + // フォームの入力データを保存 $this->entityManager->persist($SmsConfig); $this->entityManager->flush($SmsConfig); @@ -82,7 +86,5 @@ public function index(Request $request) 'SmsConfig' => $SmsConfig, 'form' => $form->createView(), ]; - } - } diff --git a/Controller/CustomerPersonalValidationController.php b/Controller/CustomerPersonalValidationController.php new file mode 100644 index 0000000..ec43123 --- /dev/null +++ b/Controller/CustomerPersonalValidationController.php @@ -0,0 +1,283 @@ +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 + * + * @return array|RedirectResponse + */ + public function deviceAuthInputOneTime(Request $request, $secret_key) + { + if ($this->isGranted('ROLE_USER')) { + // 認証済みならばマイページへ + return $this->redirectToRoute('mypage'); + } + + $error = null; + /** @var Customer $Customer */ + $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); + + if ($Customer === null) { + throw $this->createNotFoundException(); + } + + $builder = $this->formFactory->createBuilder(TwoFactorAuthSmsTypeCustomer::class); + // 入力フォーム生成 + $form = $builder->getForm(); + if ('POST' === $request->getMethod()) { + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + // メールでスロットリングをかける + $limiter = $this->deviceAuthRequestEmailLimiter->create($Customer->getEmail()); + if (!$limiter->consume()->isAccepted()) { + throw new TooManyRequestsHttpException(); + } + + $token = $form->get('one_time_token')->getData(); + if (!$this->checkDeviceToken($Customer, $token)) { + // ワンタイムトークン不一致 or 有効期限切れ + $error = trans('front.2fa.onetime.invalid_message__reinput'); + } else { + // ワンタイムトークン一致 + // 送信電話番号をセッションより取得 + $phoneNumber = $this->session->get(CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER); + // 認証済みの電話番号でないかチェック + if ($this->customerRepository->count(['device_authed_phone_number' => $phoneNumber]) === 0) { + // 未認証であれば登録 + $Customer->setDeviceAuthed(true); + $Customer->setDeviceAuthedPhoneNumber($phoneNumber); + $Customer->setDeviceAuthOneTimeToken(null); + $Customer->setDeviceAuthOneTimeTokenExpire(null); + $this->entityManager->persist($Customer); + $this->entityManager->flush(); + $this->session->remove(CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER); + + // アクティベーション実行 + return $this->redirectToRoute( + 'entry_activate', + ['secret_key' => $secret_key] + ); + } else { + // 認証済の場合はスキップ + log_warning('[デバイス認証(SMS)] 既に認証済みの電話番号指定'); + $error = trans('front.2fa.onetime.invalid_message__reinput'); + } + } + } else { + $error = trans('front.2fa.onetime.invalid_message__reinput'); + } + } + + return [ + 'form' => $form->createView(), + 'secret_key' => $secret_key, + 'Customer' => $Customer, + 'error' => $error, + ]; + } + + /** + * (デバイス認証時)デバイス認証 送信先入力画面. + * + * @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 + * + * @return array|RedirectResponse + * + * @throws ConfigurationException + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + * @throws TwilioException + */ + public function deviceAuthSendOneTime(Request $request, $secret_key) + { + if ($this->isGranted('ROLE_USER')) { + // 認証済みならばマイページへ + return $this->redirectToRoute('mypage'); + } + + $error = null; + /** @var Customer $Customer */ + $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); + if ($Customer === null) { + throw $this->createNotFoundException(); + } + $builder = $this->formFactory->createBuilder(TwoFactorAuthPhoneNumberTypeCustomer::class); + // 入力フォーム生成 + $form = $builder->getForm(); + if ('POST' === $request->getMethod()) { + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + // メールでスロットリングをかける + $limiter = $this->deviceAuthRequestEmailLimiter->create($Customer->getEmail()); + if (!$limiter->consume()->isAccepted()) { + throw new TooManyRequestsHttpException(); + } + // 認証済みの電話番号でないかチェック + $phoneNumber = $form->get('phone_number')->getData(); + if ($this->customerRepository->count(['device_authed_phone_number' => $phoneNumber]) === 0) { + // 未認証の場合、入力電話番号へワンタイムコードを送信 + $this->sendDeviceToken($Customer, $phoneNumber); + // 送信電話番号をセッションへ一時格納 + $this->session->set( + CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER, + $phoneNumber + ); + } else { + // 認証済の場合はスキップ + log_warning('[デバイス認証(SMS)] 既に認証済みの電話番号指定'); + } + + return $this->redirectToRoute( + 'plg_customer_2fa_device_auth_input_onetime', + ['secret_key' => $secret_key] + ); + } else { + $error = trans('front.2fa.sms.send.failure_message'); + } + } + + return [ + 'form' => $form->createView(), + 'secret_key' => $secret_key, + 'Customer' => $Customer, + 'error' => $error, + ]; + } + + /** + * デバイス認証用のワンタイムトークンチェック. + * + * @param $Customer + * @param $token + * + * @return boolean + */ + private function checkDeviceToken($Customer, $token): bool + { + $now = new \DateTime(); + + $hashedToken = $Customer->getDeviceAuthOneTimeToken(); + $expire = $Customer->getDeviceAuthOneTimeTokenExpire(); + + // トークン検証 + return $this->customerTwoFactorAuthService->verifyOneTimeToken($hashedToken, $token) && $expire > $now; + } + + /** + * デバイス認証用のワンタイムトークンを送信. + * + * @param Customer $Customer + * @param string $phoneNumber + * + * @return MessageInstance + * + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + * @throws ConfigurationException + * @throws TwilioException + * @throws \Exception + */ + private function sendDeviceToken(Customer $Customer, string $phoneNumber) + { + // ワンタイムトークン生成・保存 + $token = $this->customerTwoFactorAuthService->generateOneTimeTokenValue(); + + $Customer->setDeviceAuthOneTimeToken($this->customerTwoFactorAuthService->hashOneTimeToken($token)); + $Customer->setDeviceAuthOneTimeTokenExpire($this->customerTwoFactorAuthService->generateExpiryDate()); + + $this->entityManager->persist($Customer); + $this->entityManager->flush(); + + // ワンタイムトークン送信メッセージをレンダリング + $twig = 'TwoFactorAuthCustomer42/Resource/template/default/sms/onetime_message.twig'; + $body = $this->twig->render($twig, [ + 'Customer' => $Customer, + 'token' => $token, + ]); + + // SMS送信 + return $this->customerTwoFactorAuthService->sendBySms($phoneNumber, $body); + } +} diff --git a/Controller/TwoFactorAuthCustomerController.php b/Controller/TwoFactorAuthCustomerController.php index f644c56..568b907 100644 --- a/Controller/TwoFactorAuthCustomerController.php +++ b/Controller/TwoFactorAuthCustomerController.php @@ -1,203 +1,65 @@ encoderFactory = $encoderFactory; + Environment $twig + ) { $this->customerRepository = $customerRepository; - $this->tokenStorage = $tokenStorage; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; $this->twig = $twig; } - /** - * (デバイス認証時)デバイス認証 送信先入力画面. - * @Route("/two_factor_auth/device_auth/send_onetime/{secret_key}", name="plg_customer_2fa_device_auth_send_onetime", methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/default/device_auth/send.twig") - */ - public function deviceAuthSendOneTime(Request $request, $secret_key) - { - if ($this->isDeviceAuthed()) { - // 認証済みならばマイページへ - return $this->redirectToRoute('mypage'); - } - - $error = null; - /** @var Customer $Customer */ - $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); - $builder = $this->formFactory->createBuilder(TwoFactorAuthPhoneNumberTypeCustomer::class); - $form = null; - $auth_key = null; - // 入力フォーム生成 - $form = $builder->getForm(); - if ('POST' === $request->getMethod()) { - $form->handleRequest($request); - $phoneNumber = $form->get('phone_number')->getData(); - if ($form->isSubmitted() && $form->isValid()) { - // 他のデバイスで既に認証済みの電話番号かチェック - if ($this->customerRepository->findBy(['device_authed_phone_number' => $phoneNumber]) == null) { - // 認証されていない電話番号の場合 - // 入力電話番号へワンタイムコードを送信 - $this->sendDeviceToken($Customer, $phoneNumber); - // 送信電話番号をセッションへ一時格納 - $this->session->set( - CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER, - $phoneNumber - ); - } else { - log_warning('[デバイス認証(SMS)] 既に認証済みの電話番号指定'); - } - $response = new RedirectResponse( - $this->generateUrl( - 'plg_customer_2fa_device_auth_input_onetime', - ['secret_key' => $secret_key] - ) - ); - return $response; - } else { - $error = trans('front.2fa.sms.send.failure_message'); - } - } - - return [ - 'form' => $form->createView(), - 'secret_key' => $secret_key, - 'Customer' => $Customer, - 'error' => $error, - ]; - } - - /** - * (デバイス認証時)デバイス認証ワンタイムトークン入力画面. - * @Route("/two_factor_auth/device_auth/input_onetime/{secret_key}", name="plg_customer_2fa_device_auth_input_onetime", methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/default/device_auth/input.twig") - */ - public function deviceAuthInputOneTime(Request $request, $secret_key) - { - if ($this->isDeviceAuthed()) { - // 認証済みならばマイページへ - return $this->redirectToRoute('mypage'); - } - - $error = null; - /** @var Customer $Customer */ - $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); - $builder = $this->formFactory->createBuilder(TwoFactorAuthSmsTypeCustomer::class); - $form = null; - // 入力フォーム生成 - $form = $builder->getForm(); - if ('POST' === $request->getMethod()) { - $form->handleRequest($request); - $token = $form->get('one_time_token')->getData(); - if ($form->isSubmitted() && $form->isValid()) { - if (!$this->checkDeviceToken($Customer, $token)) { - // ワンタイムトークン不一致 or 有効期限切れ - $error = trans('front.2fa.onetime.invalid_message__reinput'); - } else { - // 送信電話番号をセッションより取得 - $phoneNumber = $this->session->get(CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER); - // ワンタイムトークン一致 - // デバイス認証完了 - if($Customer->getDeviceAuthedPhoneNumber() === $phoneNumber) { - // 既に認証済みの電話番号の場合は、更新しない - $response = new RedirectResponse( - $this->generateUrl( - 'entry_activate', - ['secret_key' => $secret_key] - ) - ); - return $response; - } - - $Customer->setDeviceAuthed(true); - $Customer->setDeviceAuthedPhoneNumber($phoneNumber); - $Customer->setDeviceAuthOneTimeTokenExpire(null); - $this->entityManager->persist($Customer); - $this->entityManager->flush(); - $this->session->remove(CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER); - - // アクティベーション実行 - $response = new RedirectResponse( - $this->generateUrl( - 'entry_activate', - ['secret_key' => $secret_key] - ) - ); - return $response; - } - } else { - $error = trans('front.2fa.onetime.invalid_message__reinput'); - } - } - - return [ - 'form' => $form->createView(), - 'secret_key' => $secret_key, - 'Customer' => $Customer, - 'error' => $error, - ]; - } - /** * (ログイン時)二段階認証設定(選択)画面. - * @Route("/two_factor_auth/select_type", name="plg_customer_2fa_auth_type_select", methods={"GET", "POST"}) + * + * @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") */ public function selectAuthType(Request $request) @@ -206,23 +68,25 @@ public function selectAuthType(Request $request) return $this->redirectToRoute($this->getCallbackRoute()); } - $error = null; /** @var Customer $Customer */ $Customer = $this->getUser(); + + // 2段階認証方式が選択されている場合は、その方式の初回認証画面へ遷移 + if ($Customer !== null && $Customer->getTwoFactorAuthType() !== null) { + return $this->redirectToRoute($Customer->getTwoFactorAuthType()->getRoute()); + } + + $error = null; $builder = $this->formFactory->createBuilder(TwoFactorAuthTypeCustomer::class); - $form = null; - $auth_key = null; // 入力フォーム生成 $form = $builder->getForm(); if ('POST' === $request->getMethod()) { - $form = $builder->getForm(); $form->handleRequest($request); - $TwoFactorAuthType = $form->get('two_factor_auth_type')->getData(); if ($form->isSubmitted() && $form->isValid()) { // 選択された2段階認証方式を更新 + $TwoFactorAuthType = $form->get('two_factor_auth_type')->getData(); $Customer->setTwoFactorAuthType($TwoFactorAuthType); // 2段階認証を有効に更新 - $Customer->setTwoFactorAuth(true); $this->entityManager->persist($Customer); $this->entityManager->flush(); // 初回認証を実施 @@ -239,82 +103,31 @@ public function selectAuthType(Request $request) ]; } - /** - * デバイス認証済みか否か. - * - * @return boolean - */ - protected function isDeviceAuthed() - { - /** @var Customer $Customer */ - $Customer = $this->getUser(); - if ($Customer != null && $Customer->isDeviceAuthed()) { - return true; - } - return false; - } - /** * 認証済みか否か. * * @return boolean */ - protected function isTwoFactorAuthed() + protected function isTwoFactorAuthed(): bool { /** @var Customer $Customer */ $Customer = $this->getUser(); - if (!$this->customerTwoFactorAuthService->isAuthed($Customer, $this->getCallbackRoute())) { + if ($Customer != null && !$this->customerTwoFactorAuthService->isAuthed($Customer, $this->getCallbackRoute())) { return false; } + return true; } /** * コールバックルートの取得. + * * @return string */ - protected function getCallbackRoute():string + protected function getCallbackRoute(): string { $route = $this->session->get(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL); - return ($route != null) ? $route : 'mypage'; - } - - /** - * デバイス認証用のワンタイムトークンを送信. - * - * @param \Eccube\Entity\Customer $Customer - * @param string $phoneNumber - * - */ - private function sendDeviceToken($Customer, $phoneNumber) - { - // ワンタイムトークン生成・保存 - $token = $Customer->createDeviceAuthOneTimeToken(); - $this->entityManager->persist($Customer); - $this->entityManager->flush(); - - // ワンタイムトークン送信メッセージをレンダリング - $twig = 'TwoFactorAuthCustomer42/Resource/template/default/sms/onetime_message.twig'; - $body = $this->twig->render($twig , [ - 'Customer' => $Customer, - 'token' => $token, - ]); - - // SMS送信 - return $this->customerTwoFactorAuthService->sendBySms($Customer, $phoneNumber, $body); - } - /** - * デバイス認証用のワンタイムトークンチェック. - * - * @return boolean - */ - private function checkDeviceToken($Customer, $token) - { - $now = new \DateTime(); - if ($Customer->getDeviceAuthOneTimeToken() !== $token || $Customer->getDeviceAuthOneTimeTokenExpire() < $now) { - return false; - } - return true; + return ($route != null) ? $route : 'mypage'; } } diff --git a/Entity/BaseInfoTrait.php b/Entity/BaseInfoTrait.php index 7d663e0..0ceda8d 100644 --- a/Entity/BaseInfoTrait.php +++ b/Entity/BaseInfoTrait.php @@ -1,5 +1,16 @@ two_factor_auth_use = $two_factor_auth_use; } - /** - * SMS通知の設定 - * @var bool - * @ORM\Column(name="option_activate_device", type="boolean", nullable=false, options={"default":false}) - */ - private bool $option_activate_device; /** * @return bool */ @@ -53,5 +69,4 @@ 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 410a259..6359fc3 100644 --- a/Entity/CustomerTrait.php +++ b/Entity/CustomerTrait.php @@ -1,10 +1,21 @@ setDeviceAuthOneTimeToken($token); - $this->setDeviceAuthOneTimeTokenExpire($now->modify('+5 mins')); - return $token; - } + private $TwoFactorAuthCustomerCookies; /** * @return string @@ -90,13 +85,23 @@ public function getDeviceAuthOneTimeToken(): ?string } /** - * @param string $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; } + /** + * Get resetExpire. + * + * @return \DateTime|null + */ + public function getDeviceAuthOneTimeTokenExpire() + { + return $this->device_auth_one_time_token_expire; + } + /** * Set oneTimeTokenExpire. * @@ -111,16 +116,6 @@ public function setDeviceAuthOneTimeTokenExpire($deviceAuthOneTimeTokenExpire = return $this; } - /** - * Get resetExpire. - * - * @return \DateTime|null - */ - public function getDeviceAuthOneTimeTokenExpire() - { - return $this->device_auth_one_time_token_expire; - } - /** * @return bool */ @@ -130,7 +125,7 @@ public function isDeviceAuthed(): bool } /** - * @param bool $two_factor_auth + * @param bool $device_authed */ public function setDeviceAuthed(bool $device_authed): void { @@ -146,35 +141,27 @@ public function getDeviceAuthedPhoneNumber(): ?string } /** - * @param string $device_authed_phone_number + * @param string|null $device_authed_phone_number */ - public function setDeviceAuthedPhoneNumber(string $device_authed_phone_number): void + public function setDeviceAuthedPhoneNumber(?string $device_authed_phone_number): void { $this->device_authed_phone_number = $device_authed_phone_number; } /** - * @return bool - */ - public function isTwoFactorAuth(): bool - { - return $this->two_factor_auth; - } - - /** - * @param bool $two_factor_auth + * Get sex. + * + * @return TwoFactorAuthType|null */ - public function setTwoFactorAuth(bool $two_factor_auth): void + public function getTwoFactorAuthType() { - $this->two_factor_auth = $two_factor_auth; + return $this->TwoFactorAuthType; } /** - * Set two factor auth type. - * - * @param TwoFactorAuthType|null $sex + * Set two-factor auth type. * - * @return Customer + * @param TwoFactorAuthType|null $twoFactorAuthType */ public function setTwoFactorAuthType(TwoFactorAuthType $twoFactorAuthType = null) { @@ -184,13 +171,18 @@ public function setTwoFactorAuthType(TwoFactorAuthType $twoFactorAuthType = null } /** - * Get sex. - * - * @return TwoFactorAuthType|null + * @return Collection */ - public function getTwoFactorAuthType() + public function getTwoFactorAuthCustomerCookies(): Collection { - return $this->TwoFactorAuthType; + 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 703c0a0..94b9149 100644 --- a/Entity/TwoFactorAuthConfig.php +++ b/Entity/TwoFactorAuthConfig.php @@ -15,8 +15,8 @@ use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; -use Doctrine\Common\Collections\ArrayCollection; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Validator\Constraints as Assert; /** * TwoFactorConfig @@ -53,6 +53,8 @@ class TwoFactorAuthConfig extends AbstractEntity */ private $api_secret = null; + private $plain_api_secret; + /** * @var string * @@ -67,13 +69,6 @@ class TwoFactorAuthConfig extends AbstractEntity */ private $include_routes = null; - /** - * @var string - * - * @ORM\Column(name="exclude_routes", type="text", nullable=true) - */ - private $exclude_routes = null; - /** * Constructor. */ @@ -91,20 +86,6 @@ public function getId() return $this->id; } - /** - * Set api_key. - * - * @param string $apiKey - * - * @return TwoFactorAuthConfig - */ - public function setApiKey($apiKey) - { - $this->api_key = $apiKey; - - return $this; - } - /** * Get api_key. * @@ -116,15 +97,15 @@ public function getApiKey() } /** - * Set api_secret. + * Set api_key. * - * @param string $apiSecret + * @param string $apiKey * * @return TwoFactorAuthConfig */ - public function setApiSecret($apiSecret) + public function setApiKey($apiKey) { - $this->api_secret = $apiSecret; + $this->api_key = $apiKey; return $this; } @@ -140,15 +121,15 @@ public function getApiSecret() } /** - * Set from phone number. + * Set api_secret. * - * @param string $fromTel + * @param string $apiSecret * * @return TwoFactorAuthConfig */ - public function setFromPhonenumber($fromTel) + public function setApiSecret($apiSecret) { - $this->from_phone_number = $fromTel; + $this->api_secret = $apiSecret; return $this; } @@ -158,47 +139,43 @@ public function setFromPhonenumber($fromTel) * * @return string */ - public function getFromPhonenumber() + public function getFromPhoneNumber() { return $this->from_phone_number; } /** - * Set exclude_routes. + * Set from phone number. * - * @param string|null $exclude_routes + * @param string $fromPhoneNumber * * @return TwoFactorAuthConfig */ - public function setExcludeRoutes($exclude_routes = null) + public function setFromPhoneNumber(string $fromPhoneNumber) { - $this->exclude_routes = $exclude_routes; + $this->from_phone_number = $fromPhoneNumber; return $this; } - /** - * Get exclude_routes. - * - * @return string|null - */ - public function getExcludeRoutes() + public function addIncludeRoute(string $route) { - return $this->exclude_routes; + $routes = $this->getRoutes($this->getIncludeRoutes()); + + if (!in_array($route, $routes)) { + $this->setIncludeRoutes($this->include_routes.PHP_EOL.$route); + } + + return $this; } - /** - * Set include_routes. - * - * @param string|null $include_routes - * - * @return TwoFactorAuthConfig - */ - public function setIncludeRoutes($include_routes = null) + private function getRoutes(?string $routes): array { - $this->include_routes = $include_routes; + if (!$routes) { + return []; + } - return $this; + return explode(PHP_EOL, $routes); } /** @@ -211,13 +188,16 @@ public function getIncludeRoutes() return $this->include_routes; } - public function addIncludeRoute(string $route) + /** + * Set include_routes. + * + * @param string|null $include_routes + * + * @return TwoFactorAuthConfig + */ + public function setIncludeRoutes($include_routes = null) { - $routes = $this->getRoutes($this->getIncludeRoutes()); - - if (!in_array($route, $routes)) { - $this->setIncludeRoutes($this->include_routes . PHP_EOL . $route); - } + $this->include_routes = $include_routes; return $this; } @@ -227,47 +207,35 @@ public function removeIncludeRoute(string $route) $routes = $this->getRoutes($this->getIncludeRoutes()); if (in_array($route, $routes)) { - $routes = array_splice($routes, array_search($route, $routes, true), 1); + $routes = array_diff($routes, [$route]); $this->setIncludeRoutes($this->getRoutesAsString($routes)); } return $this; } - public function addExcludeRoute(string $route) + private function getRoutesAsString(array $routes): string { - $routes = $this->getRoutes($this->getExcludeRoutes()); - - if (!in_array($route, $routes)) { - $this->setExcludeRoutes($this->exclude_routes . PHP_EOL . $route); - } - - return $this; + return implode(PHP_EOL, $routes); } - public function removeExcludeRoute(string $route) + /** + * @param string|null $plain_api_secret + * + * @return TwoFactorAuthConfig + */ + public function setPlainApiSecret(?string $plain_api_secret): TwoFactorAuthConfig { - $routes = $this->getRoutes($this->getExcludeRoutes()); - - if (in_array($route, $routes)) { - $routes = array_splice($routes, array_search($route, $routes, true), 1); - $this->setExcludeRoutes($this->getRoutesAsString($routes)); - } + $this->plain_api_secret = $plain_api_secret; return $this; } - private function getRoutes(?string $routes): array - { - if (!$routes) { - return []; - } - return explode(PHP_EOL, $routes); - } - - private function getRoutesAsString(array $routes): string + /** + * @return mixed + */ + public function getPlainApiSecret(): ?string { - return implode(PHP_EOL, $routes); + return $this->plain_api_secret; } - } diff --git a/Entity/TwoFactorAuthCustomerCookie.php b/Entity/TwoFactorAuthCustomerCookie.php new file mode 100644 index 0000000..c88c42e --- /dev/null +++ b/Entity/TwoFactorAuthCustomerCookie.php @@ -0,0 +1,197 @@ +setUpdatedAt(new \DateTime('now')); + if (!isset($this->createdAt) || $this->getCreatedAt() === null) { + $this->setCreatedAt(new \DateTime('now')); + } + } + + /** + * @return \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 + { + return $this->id; + } + + /** + * @return 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 + { + return $this->cookie_expire_date; + } + + /** + * @param \DateTime $cookie_expire_date + */ + public function setCookieExpireDate(\DateTime $cookie_expire_date): void + { + $this->cookie_expire_date = $cookie_expire_date; + } + + /** + * @return \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 bbad19c..0db26b0 100644 --- a/Entity/TwoFactorAuthType.php +++ b/Entity/TwoFactorAuthType.php @@ -15,7 +15,6 @@ use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; -use Doctrine\Common\Collections\ArrayCollection; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** @@ -42,17 +41,24 @@ class TwoFactorAuthType extends AbstractEntity /** * @var string * - * @ORM\Column(name="name", type="string", nullable=true, length=200, unique=true) + * @ORM\Column(name="name", type="string", nullable=false, length=200, unique=true) */ - private $name = null; + private $name; /** * @var string * - * @ORM\Column(name="route", type="string", nullable=true, length=200, unique=true) + * @ORM\Column(name="route", type="string", nullable=false, length=200, unique=true) */ private $route = null; + /** + * @var boolean + * + * @ORM\Column(name="is_disabled", type="boolean", nullable=false) + */ + private $isDisabled = false; + /** * Constructor. */ @@ -70,6 +76,16 @@ public function getId() return $this->id; } + /** + * Get name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + /** * Set name. * @@ -85,13 +101,13 @@ public function setName($name) } /** - * Get name. + * Get route. * * @return string */ - public function getName() + public function getRoute() { - return $this->name; + return $this->route; } /** @@ -109,13 +125,18 @@ public function setRoute($route) } /** - * Get route. - * - * @return string + * @return bool */ - public function getRoute() + public function isDisabled(): bool { - return $this->route; + return $this->isDisabled; } + /** + * @param bool $isDisabled + */ + public function setIsDisabled(bool $isDisabled): void + { + $this->isDisabled = $isDisabled; + } } diff --git a/Event.php b/Event.php index 2abe661..54c7850 100644 --- a/Event.php +++ b/Event.php @@ -13,18 +13,9 @@ namespace Plugin\TwoFactorAuthCustomer42; -use Eccube\Entity\BaseInfo; -use Eccube\Repository\BaseInfoRepository; -use Doctrine\ORM\EntityManagerInterface; -use Eccube\Event\EccubeEvents; -use Eccube\Event\EventArgs; use Eccube\Event\TemplateEvent; -use Eccube\Request\Context; -use Plugin\TwoFactorAuthCustomer42\Repository\BaseTwoFactorAuthSettingRepository; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; +use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Filesystem\Filesystem; /** * Class Event. @@ -32,57 +23,18 @@ class Event implements EventSubscriberInterface { /** - * @var ContainerInterface + * @var bool */ - protected $container; - - /** - * @var BaseInfo - */ - protected $BaseInfo; - - /** - * @var CustomerTwoFactorAuthService - */ - protected $customerTwoFactorAuthService; - - /** - * @var EntityManagerInterface - */ - private $entityManager; - - /** - * @var \Twig_Environment - */ - private $twig; - - /** - * @var NotifierInterface - */ - //private $notifier; + private bool $hasActiveAuthType; /** * Event constructor. * - * @param ContainerInterface $container - * @param BaseInfoRepository $baseInfoRepository - * @param EntityManagerInterface $entityManager - * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService - * @param \Twig_Environment $twig + * @throws \Exception */ - public function __construct( - ContainerInterface $container, - BaseInfoRepository $baseInfoRepository, - EntityManagerInterface $entityManager, - CustomerTwoFactorAuthService $customerTwoFactorAuthService, - \Twig_Environment $twig - ) + public function __construct(TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository) { - $this->container = $container; - $this->BaseInfo = $baseInfoRepository->get(); - $this->entityManager = $entityManager; - $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->twig = $twig; + $this->hasActiveAuthType = $twoFactorAuthTypeRepository->count(['isDisabled' => false]) > 0; } public static function getSubscribedEvents(): array @@ -101,17 +53,19 @@ public static function getSubscribedEvents(): array */ public function onRenderAdminShopSettingEdit(TemplateEvent $event) { - // add twig + // add 本人確認認証 twig $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/shop_edit_sms.twig'; $event->addSnippet($twig); - // add twig - $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/shop_edit_tfa.twig'; - $event->addSnippet($twig); + if ($this->hasActiveAuthType) { + // add 2段階認証設定 twig + $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/shop_edit_tfa.twig'; + $event->addSnippet($twig); + } } /** - * [/admin/customer/edit]表示の時のEvent Fork. + * [/admin/customer/edit]表示の時のEvent Hook. * 二段階認証関連項目を追加する. * * @param TemplateEvent $event @@ -122,5 +76,4 @@ public function onRenderAdminCustomerEdit(TemplateEvent $event) $twig = 'TwoFactorAuthCustomer42/Resource/template/admin/customer_edit.twig'; $event->addSnippet($twig); } - } diff --git a/EventListener/CustomerPersonalValidationListener.php b/EventListener/CustomerPersonalValidationListener.php new file mode 100644 index 0000000..01ffb4f --- /dev/null +++ b/EventListener/CustomerPersonalValidationListener.php @@ -0,0 +1,173 @@ +requestContext = $requestContext; + $this->router = $router; + $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; + $this->baseInfo = $baseInfoRepository->find(1); + $this->customerRepository = $customerRepository; + } + + /** + * @return array + */ + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelController', 7], + ]; + } + + /** + * リクエスト受信時イベントハンドラ. + * + * @param ControllerArgumentsEvent $event + */ + public function onKernelController(ControllerArgumentsEvent $event) + { + if (!$event->isMainRequest()) { + // サブリクエストの場合、処理なし + return; + } + + if ($this->requestContext->isAdmin()) { + // バックエンドURLの場合、処理なし + return; + } + + if ( + ($this->baseInfo->isOptionCustomerActivate() && !$this->baseInfo->isOptionActivateDevice()) + || + !$this->baseInfo->isOptionCustomerActivate() + ) { + // デバイス認証なし かつ 2段階認証使用しない場合は処理なし + return; + } + + $route = $event->getRequest()->attributes->get('_route'); + + if ($this->isActivationRoute($route)) { + // デバイス認証(アクティベーション前に介入) + $this->deviceAuth($event); + } + } + + /** + * アクティベーションルートかチェック. + * + * @param string $route + * + * @return bool + */ + private function isActivationRoute(string $route): bool + { + // ルートで認証 + return $route === self::ACTIVATE_ROUTE; + } + + /** + * デバイス認証. + * + * @param mixed $event + * + * @throws NotFoundHttpException + */ + private function deviceAuth($event) + { + // アクティベーション + $secret_key = $event->getRequest()->attributes->get('secret_key'); + + $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); + if (is_null($Customer)) { + throw new NotFoundHttpException(); + } + + if ($Customer->isDeviceAuthed()) { + return; + } + + // デバイス認証されていない場合 + if ($this->baseInfo->isOptionActivateDevice() && $this->baseInfo->isOptionCustomerActivate()) { + // 仮会員登録機能:有効 / SMSによる本人認証:有効の場合 デバイス認証画面へリダイレクト + $url = $this->router->generate( + 'plg_customer_2fa_device_auth_send_onetime', + ['secret_key' => $secret_key] + ); + + $event->setController(function () use ($url) { + return new RedirectResponse($url, 302); + }); + } + } +} diff --git a/EventListener/CustomerTwoFactorAuthListener.php b/EventListener/CustomerTwoFactorAuthListener.php old mode 100644 new mode 100755 index b0c1d38..fdf0ddc --- a/EventListener/CustomerTwoFactorAuthListener.php +++ b/EventListener/CustomerTwoFactorAuthListener.php @@ -13,128 +13,96 @@ namespace Plugin\TwoFactorAuthCustomer42\EventListener; -use Doctrine\ORM\EntityManagerInterface; use Eccube\Common\EccubeConfig; -use Eccube\Entity\Master\CustomerStatus; +use Eccube\Entity\BaseInfo; use Eccube\Entity\Customer; +use Eccube\Entity\Master\CustomerStatus; use Eccube\Repository\BaseInfoRepository; -use Eccube\Repository\CustomerRepository; use Eccube\Request\Context; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; +use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthCustomerCookieRepository; +use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Exception as HttpException; 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 { - - /** - * アクティベーション - */ - public const ACTIVATE_ROUTE = 'entry_activate'; - - /** - * @var EntityManagerInterface - */ - private $entityManager; - /** * @var EccubeConfig */ protected $eccubeConfig; - /** * @var Context */ protected $requestContext; - /** * @var UrlGeneratorInterface */ protected $router; - /** * @var CustomerTwoFactorAuthService */ protected $customerTwoFactorAuthService; - - /** - * @var BaseInfoRepository - */ - protected BaseInfoRepository $baseInfoRepository; - - /** - * @var CustomerRepository - */ - protected CustomerRepository $customerRepository; - /** * @var TwoFactorAuthTypeRepository */ protected TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository; - /** - * @var \Eccube\Entity\BaseInfo|object|null + * @var TwoFactorAuthCustomerCookieRepository + */ + protected TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository; + /** + * @var BaseInfo|object|null */ protected $baseInfo; - /** * @var Session */ protected $session; - /** - * 除外ルート. + * 通常(ログイン・マイページ)ルート. */ - protected $exclude_routes; - + protected $default_routes; /** - * 個別認証ルート. + * 重要操作ルート. */ protected $include_routes; /** - * @param EntityManagerInterface $entityManager - * @param EccubeConfig $eccubeConfig * @param Context $requestContext * @param UrlGeneratorInterface $router * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService - * @param BaseInfoRepository $baseInfoRepository - * @param CustomerRepository $customerRepository * @param TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository - * @param SessionInterface $session + * @param TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository + * @param BaseInfoRepository $baseInfoRepository + * @param RequestStack $requestStack */ public function __construct( - EntityManagerInterface $entityManager, - EccubeConfig $eccubeConfig, - Context $requestContext, - UrlGeneratorInterface $router, + Context $requestContext, + UrlGeneratorInterface $router, CustomerTwoFactorAuthService $customerTwoFactorAuthService, - BaseInfoRepository $baseInfoRepository, - CustomerRepository $customerRepository, - TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, - SessionInterface $session + TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, + TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository, + BaseInfoRepository $baseInfoRepository, + RequestStack $requestStack ) { - $this->entityManager = $entityManager; - $this->eccubeConfig = $eccubeConfig; $this->requestContext = $requestContext; $this->router = $router; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->baseInfoRepository = $baseInfoRepository; - $this->baseInfo = $this->baseInfoRepository->find(1); - $this->customerRepository = $customerRepository; + $this->baseInfo = $baseInfoRepository->find(1); $this->twoFactorAuthTypeRepository = $twoFactorAuthTypeRepository; - $this->session = $session; + $this->twoFactorAuthCustomerCookieRepository = $twoFactorAuthCustomerCookieRepository; + $this->session = $requestStack->getSession(); + $this->default_routes = $this->customerTwoFactorAuthService->getDefaultAuthRoutes(); $this->include_routes = $this->customerTwoFactorAuthService->getIncludeRoutes(); - $this->exclude_routes = $this->customerTwoFactorAuthService->getExcludeRoutes(); } /** @@ -144,12 +112,14 @@ public static function getSubscribedEvents(): array { return [ KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelController', 7], - LoginSuccessEvent::class => ['onLoginSuccess'] + LoginSuccessEvent::class => ['onLoginSuccess'], + LogoutEvent::class => 'logoutEvent', ]; } /** * リクエスト受信時イベントハンドラ. + * * @param ControllerArgumentsEvent $event */ public function onKernelController(ControllerArgumentsEvent $event) @@ -164,44 +134,37 @@ public function onKernelController(ControllerArgumentsEvent $event) return; } - if (($this->baseInfo->isOptionCustomerActivate() && !$this->baseInfo->isOptionActivateDevice()) - && !$this->baseInfo->isTwoFactorAuthUse()) { - // デバイス認証なし かつ 2段階認証使用しない場合は処理なし + if (!$this->baseInfo->isTwoFactorAuthUse()) { + // 2段階認証使用しない場合は処理なし return; } $route = $event->getRequest()->attributes->get('_route'); $uri = $event->getRequest()->getRequestUri(); - if ($this->isActivationRoute($route)) { - // デバイス認証(アクティベーション前に介入) - $this->deviceAuth($event); - return; - } - $Customer = $this->requestContext->getCurrentUser(); - if ($Customer && $Customer instanceof Customer) { - - if ($Customer->getStatus()->getId() !== CustomerStatus::ACTIVE) { + if ($Customer instanceof Customer) { + if ($Customer->getStatus()->getId() !== CustomerStatus::REGULAR) { // ログインしていない場合、処理なし return; } - if (!$this->isIncludeRoute($route, $uri)) { + if (!$this->isDefaultRoute($route, $uri) && !$this->isIncludeRoute($route, $uri)) { // 重要操作指定ではなく、マイページ系列ではない場合、処理なし return; } - $this->multifactorAuth($event, $Customer, $route, $uri); + $this->multiFactorAuth($event, $Customer, $route); } - - return; } /** * ログイン完了 イベントハンドラ. + * * @param LoginSuccessEvent $event + * + * @return RedirectResponse|void */ public function onLoginSuccess(LoginSuccessEvent $event) { @@ -215,87 +178,135 @@ public function onLoginSuccess(LoginSuccessEvent $event) return; } - $this->multifactorAuth( + if ($this->requestContext->getCurrentUser() === null) { + // ログインしていない場合は処理なし + return; + } + + if ($this->requestContext->getCurrentUser()->getTwoFactorAuthType() !== null && + $this->requestContext->getCurrentUser()->getTwoFactorAuthType()->isDisabled()) { + // ユーザーが選択した2段階認証方式は無効になっている場合、ログアウトさせる。 + return new RedirectResponse($this->router->generate('logout'), 302); + } + + $this->multiFactorAuth( $event, $this->requestContext->getCurrentUser(), - $event->getRequest()->attributes->get('_route'), - $event->getRequest()->getRequestUri()); - - return; + $event->getRequest()->attributes->get('_route')); } /** - * デバイス認証. - * @param mixed $event - * @throws HttpException\NotFoundHttpException + * ログアウトする前に全ての2FA認証クッキーを消す + * + * @param LogoutEvent $logoutEvent ログアウトイベント + * + * @return void */ - private function deviceAuth($event) + public function logoutEvent(LogoutEvent $logoutEvent) { - // アクティベーション - $secret_key = $event->getRequest()->attributes->get('secret_key'); - $Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key); - if (is_null($Customer)) { - throw new HttpException\NotFoundHttpException(); + $Customer = $this->requestContext->getCurrentUser(); + if ($Customer instanceof Customer) { + $this->customerTwoFactorAuthService->clear2AuthCookies($logoutEvent->getRequest(), $logoutEvent->getResponse()); + $this->twoFactorAuthCustomerCookieRepository->deleteByCustomer($Customer); } + } - if ($Customer->isDeviceAuthed()) { - return; - } - // デバイス認証されていない場合 - if ($this->baseInfo->isOptionActivateDevice() && $this->baseInfo->isOptionCustomerActivate()) { - // 仮会員登録機能:有効 / SMSによる本人認証:有効の場合 デバイス認証画面へリダイレクト - $url = $this->router->generate( - 'plg_customer_2fa_device_auth_send_onetime', - ['secret_key' => $secret_key], - UrlGeneratorInterface::ABSOLUTE_PATH - ); + /** + * ルート・URIが個別認証対象かチェック. + * + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isDefaultRoute(string $route, string $uri): bool + { + return $this->isTargetRoute($this->default_routes, $route, $uri); + } - $event->setController(function () use ($url) { - return new RedirectResponse($url, $status = 302); - }); + /** + * ルート・URIが対象であるかチェック. + * + * @param array $targetRoutes + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isTargetRoute(array $targetRoutes, string $route, string $uri): bool + { + // ルートで認証 + if (in_array($route, $targetRoutes)) { + return true; + } + + // URIで認証 + foreach ($targetRoutes as $r) { + if ($r != '' && $r !== '/' && strpos($uri, $r) === 0) { + return true; + } } - return; + return false; + } + + /** + * ルート・URIが個別認証対象かチェック. + * + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isIncludeRoute(string $route, string $uri): bool + { + return $this->isTargetRoute($this->include_routes, $route, $uri); } /** * 多要素認証. - * @param mixed $event - * @throws HttpException\NotFoundHttpException + * + * @param Event $event + * @param Customer $Customer + * @param string $route + * * @return mixed */ - private function multifactorAuth($event, $Customer, $route, $uri) + private function multiFactorAuth($event, $Customer, $route) { if (!$this->baseInfo->isTwoFactorAuthUse()) { // MFA無効の場合処理なし return; } + if (count($this->twoFactorAuthTypeRepository->findBy(['isDisabled' => false])) == 0) { + // 2段階認証プラグインが有効化されていない場合処理なし + return; + } + // [会員] ログイン時2段階認証状態 $is_auth = $this->customerTwoFactorAuthService->isAuthed($Customer, $route); if (!$is_auth) { log_info('[2段階認証] 実施'); - if (!$Customer->isTwoFactorAuth()) { + if ($Customer->getTwoFactorAuthType() === null) { // 2段階認証未設定 - $this->selectAuthType($event, $Customer, $route); + $this->selectAuthType($event, $route); } else { // 2段階認証設定済み $this->auth($event, $Customer, $route); } } - - return; } /** * 多要素認証方式設定画面へリダイレクト. + * * @param Event $event - * @param Customer $Customer * @param string|null $route */ - private function selectAuthType($event, Customer $Customer, ?string $route) + private function selectAuthType($event, ?string $route) { // [会員] 2段階認証が未設定の場合 // コールバックURLをセッションへ設定 @@ -310,7 +321,18 @@ private function selectAuthType($event, Customer $Customer, ?string $route) } else { $event->setResponse(new RedirectResponse($url, 302)); } - return; + } + + /** + * コールバックルートをセッションへ設定. + * + * @param string|null $route + */ + private function setCallbackRoute(?string $route) + { + if ($route) { + $this->session->set(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL, $route); + } } /** @@ -325,10 +347,16 @@ private function auth($event, Customer $Customer, ?string $route) // コールバックURLをセッションへ設定 $this->setCallbackRoute($route); // 選択された多要素認証方式で指定されているルートへリダイレクト - $url = $this->router->generate( - $Customer->getTwoFactorAuthType()->getRoute(), - [], - UrlGeneratorInterface::ABSOLUTE_PATH); + if ($Customer->getTwoFactorAuthType() !== null && $Customer->getTwoFactorAuthType()->isDisabled()) { + // ユーザーが選択した2段階認証方式は無効になっている場合、ログアウトさせる。 + $event->setController(function () { + return new RedirectResponse($this->router->generate('logout'), 302); + }); + + return; + } + + $url = $this->router->generate($Customer->getTwoFactorAuthType()->getRoute()); if ($event instanceof ControllerArgumentsEvent) { $event->setController(function () use ($url) { @@ -337,55 +365,6 @@ private function auth($event, Customer $Customer, ?string $route) } else { $event->setResponse(new RedirectResponse($url, 302)); } - return; - } - - /** - * コールバックルートをセッションへ設定. - * @param string|null $route - */ - private function setCallbackRoute(?string $route) - { - if ($route) { - $this->session->set(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL, $route); - } - } - - /** - * アクティベーションルートかチェック. - * - * @param string $route - * @param string $uri - * @return bool - */ - private function isActivationRoute(string $route): bool - { - // ルートで認証 - return $route === self::ACTIVATE_ROUTE; - } - - /** - * ルート・URIが個別認証対象かチェック. - * - * @param string $route - * @param string $uri - * @return bool - */ - private function isIncludeRoute(string $route, string $uri): bool - { - // ルートで認証 - if (in_array($route, $this->include_routes)) { - return true; - } - - // URIで認証 - foreach($this->include_routes as $r) { - if ($r != '' && $r !== '/' && strpos($uri, $r) === 0) { - return true; - } - } - - return false; } } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php index 1a8e903..7efd56a 100644 --- a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php @@ -1,10 +1,22 @@ entityManager = $entityManager; } + /** + * {@inheritDoc} + */ + public static function getExtendedTypes(): iterable + { + yield ShopMasterType::class; + } + /** * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { @@ -43,23 +62,18 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) { $form = $event->getForm(); - $form->add('two_factor_auth_use', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true - ]) - ->add('option_activate_device', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true - ]) - ; - }); - } - /** - * {@inheritDoc} - */ - public static function getExtendedTypes(): iterable - { - yield ShopMasterType::class; + if ($this->entityManager->getRepository(TwoFactorAuthType::class)->count(['isDisabled' => false]) > 0) { + $form->add('two_factor_auth_use', ToggleSwitchType::class, [ + 'required' => false, + 'mapped' => true, + ]); + } + + $form->add('option_activate_device', ToggleSwitchType::class, [ + 'required' => false, + 'mapped' => true, + ]); + }); } } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php old mode 100644 new mode 100755 index 0980730..fe6eae8 --- a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php @@ -1,17 +1,28 @@ entityManager = $entityManager; } + /** + * {@inheritDoc} + */ + public static function getExtendedTypes(): iterable + { + yield CustomerType::class; + } + /** * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { @@ -46,32 +64,20 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) { $form = $event->getForm(); - $form->add('two_factor_auth', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true - ]) - ->add('two_factor_auth_type', EntityType::class, [ + $form->add('two_factor_auth_type', EntityType::class, [ 'class' => TwoFactorAuthType::class, - 'required' => true, + 'required' => false, 'choice_label' => 'name', 'mapped' => true, + 'placeholder' => 'admin.customer.2fa.type_option.default', ]) - ->add('device_authed', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true - ]) - ->add('device_authed_phone_number', PhoneNumberType::class, [ - 'required' => false, - ]) - ; + ->add('device_authed', ToggleSwitchType::class, [ + 'required' => false, + 'mapped' => true, + ]) + ->add('device_authed_phone_number', PhoneNumberType::class, [ + 'required' => false, + ]); }); } - - /** - * {@inheritDoc} - */ - public static function getExtendedTypes(): iterable - { - yield CustomerType::class; - } } diff --git a/Form/Type/TwoFactorAuthConfigType.php b/Form/Type/TwoFactorAuthConfigType.php index 667111d..00cd14f 100644 --- a/Form/Type/TwoFactorAuthConfigType.php +++ b/Form/Type/TwoFactorAuthConfigType.php @@ -1,5 +1,16 @@ eccubeConfig = $eccubeConfig; + $this->validator = $validator; } public function buildForm(FormBuilderInterface $builder, array $options) { - $builder ->add('api_key', TextType::class, [ 'required' => true, @@ -45,22 +57,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) new Assert\Regex( [ 'pattern' => '/^[a-zA-Z0-9]+$/i', - 'message' => 'form_error.graph_only' + 'message' => 'form_error.graph_only', ] ), ], ]) - ->add('api_secret', TextType::class, [ + ->add('plain_api_secret', 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' - ] - ), ], ]) ->add('from_phone_number', TextType::class, [ @@ -71,7 +77,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) new Assert\Regex( [ 'pattern' => '/^[0-9]+$/i', - 'message' => 'form_error.numeric_only' + 'message' => 'form_error.numeric_only', ] ), ], @@ -83,20 +89,32 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'max' => $this->eccubeConfig['eccube_ltext_len'], ]), ], - ]) - ->add('exclude_routes', TextareaType::class, [ - 'required' => false, - 'constraints' => [ - new Assert\Length([ - 'max' => $this->eccubeConfig['eccube_ltext_len'], - ]), - ], ]); + + $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { + $form = $event->getForm(); + $data = $event->getData(); + + 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', + ]), + ]); + if ($errors) { + foreach ($errors as $error) { + $form['plain_api_secret']->addError(new FormError($error->getMessage())); + } + } + } + }); } /** * {@inheritDoc} - * @see \Symfony\Component\Form\AbstractType::configureOptions() + * + * @see AbstractType::configureOptions */ public function configureOptions(OptionsResolver $resolver) { @@ -104,5 +122,4 @@ public function configureOptions(OptionsResolver $resolver) 'data_class' => TwoFactorAuthConfig::class, ]); } - } diff --git a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php index 20c8b70..f6e665c 100644 --- a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php +++ b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php @@ -27,8 +27,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->add('phone_number', PhoneNumberType::class, [ 'required' => true, - ]) - ; + ]); } /** diff --git a/Form/Type/TwoFactorAuthSmsTypeCustomer.php b/Form/Type/TwoFactorAuthSmsTypeCustomer.php index 63fc945..6907926 100644 --- a/Form/Type/TwoFactorAuthSmsTypeCustomer.php +++ b/Form/Type/TwoFactorAuthSmsTypeCustomer.php @@ -41,8 +41,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'maxlength' => 6, 'style' => 'width: 100px;', ], - ]) - ; + ]); } /** diff --git a/Form/Type/TwoFactorAuthTypeCustomer.php b/Form/Type/TwoFactorAuthTypeCustomer.php index eec6029..5240525 100644 --- a/Form/Type/TwoFactorAuthTypeCustomer.php +++ b/Form/Type/TwoFactorAuthTypeCustomer.php @@ -13,10 +13,11 @@ namespace Plugin\TwoFactorAuthCustomer42\Form\Type; +use Doctrine\ORM\EntityRepository; use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Bridge\Doctrine\Form\Type\EntityType; class TwoFactorAuthTypeCustomer extends AbstractType { @@ -30,10 +31,14 @@ public function buildForm(FormBuilderInterface $builder, array $options) '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); + }, 'choice_label' => 'name', 'mapped' => true, - ]) - ; + ]); } /** diff --git a/PluginManager.php b/PluginManager.php index 720f9b3..4e40a36 100644 --- a/PluginManager.php +++ b/PluginManager.php @@ -18,9 +18,10 @@ use Eccube\Entity\Page; use Eccube\Entity\PageLayout; use Eccube\Plugin\AbstractPluginManager; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Filesystem\Filesystem; +use Eccube\Common\EccubeConfig; use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; +use Psr\Container\ContainerInterface; +use Symfony\Component\Filesystem\Filesystem; /** * Class PluginManager. @@ -29,9 +30,8 @@ class PluginManager extends AbstractPluginManager { // 設定対象ページ情報 private $pages = [ - ['plg_customer_2fa_device_auth_send_onetime', 'デバイス認証送信先入力', 'TwoFactorAuthCustomer42/Resource/template/default/device_auth/send_onetime'], - ['plg_customer_2fa_device_auth_input_onetime', 'デバイス認証トークン入力', 'TwoFactorAuthCustomer42/Resource/template/default/device_auth/input_onetime'], - ['plg_customer_2fa_device_auth_complete', 'デバイス認証完了', 'TwoFactorAuthCustomer42/Resource/template/default/device_auth/complete'], + ['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'], ]; @@ -53,27 +53,21 @@ public function enable(array $meta, ContainerInterface $container) } /** - * @param array $meta - * @param ContainerInterface $container - */ - public function disable(array $meta, ContainerInterface $container) - { - - } - - /** - * @param array $meta - * @param ContainerInterface $container + * 設定の登録. + * + * @param EntityManagerInterface $em */ - public function uninstall(array $meta, ContainerInterface $container) + protected function createConfig(EntityManagerInterface $em) { - $em = $container->get('doctrine')->getManager(); - - // twigファイルを削除 - $this->removeTwigFiles($container); + $TwoFactorAuthConfig = $em->find(TwoFactorAuthConfig::class, 1); + if ($TwoFactorAuthConfig) { + return; + } - // ページ削除 - $this->removePages($em); + // 初期値を保存 + $TwoFactorAuthConfig = new TwoFactorAuthConfig(); + $em->persist($TwoFactorAuthConfig); + $em->flush(); } /** @@ -84,14 +78,14 @@ public function uninstall(array $meta, ContainerInterface $container) protected function copyTwigFiles(ContainerInterface $container) { // テンプレートファイルコピー - $templatePath = $container->getParameter('eccube_theme_front_dir') - .'/TwoFactorAuthCustomer42/Resource/template/default'; + $templatePath = $container->get(EccubeConfig::class)->get('eccube_theme_front_dir') + . '/TwoFactorAuthCustomer42/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); } /** @@ -102,9 +96,9 @@ protected function copyTwigFiles(ContainerInterface $container) protected function createPages(EntityManagerInterface $em) { foreach ($this->pages as $p) { - $Page = $em->getRepository(Page::class)->findOneBy(['url' => $p[0]]); - if (!$Page) { - /** @var \Eccube\Entity\Page $Page */ + $hasPage = $em->getRepository(Page::class)->count(['url' => $p[0]]) > 0; + if (!$hasPage) { + /** @var Page $Page */ $Page = $em->getRepository(Page::class)->newPage(); $Page->setEditType(Page::EDIT_TYPE_DEFAULT); $Page->setUrl($p[0]); @@ -128,6 +122,21 @@ protected function createPages(EntityManagerInterface $em) } } + /** + * @param array $meta + * @param ContainerInterface $container + */ + public function disable(array $meta, ContainerInterface $container) + { + $em = $container->get('doctrine')->getManager(); + + // twigファイルを削除 + $this->removeTwigFiles($container); + + // ページ削除 + $this->removePages($em); + } + /** * Twigファイルの削除 * @@ -135,8 +144,8 @@ protected function createPages(EntityManagerInterface $em) */ protected function removeTwigFiles(ContainerInterface $container) { - $templatePath = $container->getParameter('eccube_theme_front_dir') - .'/TwoFactorAuthCustomer42'; + $templatePath = $container->get(EccubeConfig::class)->get('eccube_theme_front_dir') + . '/TwoFactorAuthCustomer42'; $fs = new Filesystem(); $fs->remove($templatePath); } @@ -150,7 +159,7 @@ protected function removePages(EntityManagerInterface $em) { foreach ($this->pages as $p) { $Page = $em->getRepository(Page::class)->findOneBy(['url' => $p[0]]); - if (!$Page) { + if ($Page !== null) { $Layout = $em->getRepository(Layout::class)->find(Layout::DEFAULT_LAYOUT_UNDERLAYER_PAGE); $PageLayout = $em->getRepository(PageLayout::class)->findOneBy(['Page' => $Page, 'Layout' => $Layout]); @@ -162,28 +171,17 @@ protected function removePages(EntityManagerInterface $em) } /** - * 設定の登録. - * - * @param EntityManagerInterface $em + * @param array $meta + * @param ContainerInterface $container */ - protected function createConfig(EntityManagerInterface $em) + public function uninstall(array $meta, ContainerInterface $container) { - $TwoFactorAuthConfig = $em->find(TwoFactorAuthConfig::class, 1); - if ($TwoFactorAuthConfig) { - return $TwoFactorAuthConfig; - } - - // 初期値を保存 - $TwoFactorAuthConfig = new TwoFactorAuthConfig(); + $em = $container->get('doctrine')->getManager(); - // 除外ルートの登録 - foreach ($this->pages as $p) { - $TwoFactorAuthConfig->addExcludeRoute($p[0]); - } - $em->persist($TwoFactorAuthConfig); - $em->flush(); + // twigファイルを削除 + $this->removeTwigFiles($container); - return; + // ページ削除 + $this->removePages($em); } - } diff --git a/Repository/TwoFactorAuthConfigRepository.php b/Repository/TwoFactorAuthConfigRepository.php index db475b3..b024e34 100644 --- a/Repository/TwoFactorAuthConfigRepository.php +++ b/Repository/TwoFactorAuthConfigRepository.php @@ -13,9 +13,10 @@ namespace Plugin\TwoFactorAuthCustomer42\Repository; -use Eccube\Repository\AbstractRepository; use Doctrine\Persistence\ManagerRegistry; +use Eccube\Repository\AbstractRepository; use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; +use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie; /** * TwoFactorAuthConfigRepository. @@ -36,11 +37,10 @@ public function __construct(ManagerRegistry $registry) } /** - * - * @return $result + * @return object|TwoFactorAuthConfig|TwoFactorAuthCustomerCookie|null $result */ public function findOne() { - return $this->findOneBy(array(), array('id' => 'DESC')); + return $this->findOneBy([], ['id' => 'DESC']); } } diff --git a/Repository/TwoFactorAuthCustomerCookieRepository.php b/Repository/TwoFactorAuthCustomerCookieRepository.php new file mode 100644 index 0000000..8d7d4f5 --- /dev/null +++ b/Repository/TwoFactorAuthCustomerCookieRepository.php @@ -0,0 +1,154 @@ +findOldCookies($customer, $cookieName); + foreach ($previousCookies as $cookie) { + $this->getEntityManager()->remove($cookie); + } + $this->getEntityManager()->flush(); + + $cookie = new TwoFactorAuthCustomerCookie(); + $cookie->setCookieName($cookieName); + $cookie->setCookieValue(StringUtil::random($CookieValueCharacterLength)); + $cookie->setCookieExpireDate($expireSeconds != 0 ? Carbon::now()->addSeconds($expireSeconds) : null); + $cookie->setCustomer($customer); + $cookie->updatedTimestamps(); + + return $cookie; + } + + /** + * 過去のクッキーデータの取得 + * + * @param Customer $customer + * @param string $cookieName + * + * @return float|int|mixed|string + */ + public function findOldCookies(Customer $customer, string $cookieName) + { + $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); + + return $this->createQueryBuilder('tfcc') + ->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, + ]) + ->getQuery() + ->getResult(); + } + + /** + * @return TwoFactorAuthCustomerCookie|null $result + */ + public function findOne() + { + return $this->findOneBy([], ['id' => 'DESC']); + } + + /*** + * 有効クッキーを取得する + * + * @param Customer $customer + * @param string $cookieName + * @return TwoFactorAuthCustomerCookie[]|null + */ + public function searchForCookie(Customer $customer, string $cookieName) + { + $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); + + return $this->createQueryBuilder('tfcc') + ->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, + ]) + ->getQuery() + ->getResult(); + } + + /*** + * 会員のクッキーを削除 + * + * @param Customer $customer + */ + public function deleteByCustomer(Customer $customer) + { + $em = $this->getEntityManager(); + $em->beginTransaction(); + + $this->createQueryBuilder('tfcc') + ->delete() + ->where('tfcc.Customer = :customer') + ->setParameter('customer', $customer) + ->getQuery() + ->execute(); + + $em->flush(); + + $em->commit(); + } + +} diff --git a/Repository/TwoFactorAuthTypeRepository.php b/Repository/TwoFactorAuthTypeRepository.php index ad96b60..5672da0 100644 --- a/Repository/TwoFactorAuthTypeRepository.php +++ b/Repository/TwoFactorAuthTypeRepository.php @@ -13,8 +13,8 @@ namespace Plugin\TwoFactorAuthCustomer42\Repository; -use Eccube\Repository\AbstractRepository; use Doctrine\Persistence\ManagerRegistry; +use Eccube\Repository\AbstractRepository; use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthType; /** @@ -36,21 +36,10 @@ public function __construct(ManagerRegistry $registry) } /** - * - * @return $result + * @return object|TwoFactorAuthType|null $result */ public function findOne() { - $qb = $this->createQueryBuilder('c')->setMaxResults(1)->select('c'); - - // 実行 - $result = null; - $results = $qb->getQuery()->getResult(); - if (!is_null($results) && count($results) > 0) { - $result = $results[0]; - } - - return $result; + return $this->findOneBy([], ['id' => 'DESC']); } - } diff --git a/Resource/config/services.yaml b/Resource/config/services.yaml index 515d862..1d5d5c8 100644 --- a/Resource/config/services.yaml +++ b/Resource/config/services.yaml @@ -1,6 +1,17 @@ eccube: rate_limiter: - device_auth_request: + plg_customer_2fa_device_auth_input_onetime: + # 実行するルーティングを指定します。 + route: plg_customer_2fa_device_auth_input_onetime + # 実行するmethodを指定します。デフォルトはPOSTです。 + method: [ 'POST' ] + # スロットリングの制御方法を設定します。ip・customerを指定できます。 + type: [ 'ip', 'customer' ] + # 試行回数を設定します。 + limit: 5 + # インターバルを設定します。 + interval: '30 minutes' + plg_customer_2fa_device_auth_send_onetime: # 実行するルーティングを指定します。 route: plg_customer_2fa_device_auth_send_onetime # 実行するmethodを指定します。デフォルトはPOSTです。 @@ -11,7 +22,11 @@ eccube: limit: 5 # インターバルを設定します。 interval: '30 minutes' - + device_auth_request_email: + route: ~ + limit: 10 + interval: '30 minutes' + parameters: env(PLUGIN_ECCUBE_2FA_CUSTOMER_COOKIE_NAME): 'plugin_eccube_customer_2fa' env(PLUGIN_ECCUBE_2FA_CUSTOMER_SMS_SEND_COOKIE_NAME): 'plugin_eccube_customer_2fa_sms' @@ -19,8 +34,14 @@ parameters: env(PLUGIN_ECCUBE_2FA_CUSTOMER_EXPIRE): '3600' env(PLUGIN_ECCUBE_2FA_ROUTE_CUSTOMER_COOKIE_NAME): 'plugin_eccube_route_customer_2fa' env(PLUGIN_ECCUBE_2FA_ROUTE_CUSTOMER_EXPIRE): '3600' + env(PLUGIN_ECCUBE_2FA_ROUTE_COOKIE_VALUE_CHARACTER_LENGTH): '64' + env(PLUGIN_ECCUBE_2FA_ONE_TIME_TOKEN_LENGTH): '6' + env(PLUGIN_ECCUBE_2FA_ONE_TIME_TOKEN_EXPIRE_AFTER_SECONDS): '300' plugin_eccube_2fa_customer_cookie_name: '%env(PLUGIN_ECCUBE_2FA_CUSTOMER_COOKIE_NAME)%' plugin_eccube_2fa_route_customer_cookie_name: '%env(PLUGIN_ECCUBE_2FA_ROUTE_CUSTOMER_COOKIE_NAME)%' plugin_eccube_2fa_customer_expire: '%env(PLUGIN_ECCUBE_2FA_CUSTOMER_EXPIRE)%' - plugin_eccube_2fa_route_customer_expire: '%env(PLUGIN_ECCUBE_2FA_ROUTE_CUSTOMER_EXPIRE)%' \ No newline at end of file + plugin_eccube_2fa_route_customer_expire: '%env(PLUGIN_ECCUBE_2FA_ROUTE_CUSTOMER_EXPIRE)%' + plugin_eccube_2fa_route_cookie_value_character_length: '%env(PLUGIN_ECCUBE_2FA_ROUTE_COOKIE_VALUE_CHARACTER_LENGTH)%' + plugin_eccube_2fa_one_time_token_length: '%env(PLUGIN_ECCUBE_2FA_ONE_TIME_TOKEN_LENGTH)%' + plugin_eccube_2fa_one_time_token_expire_after_seconds: '%env(PLUGIN_ECCUBE_2FA_ONE_TIME_TOKEN_EXPIRE_AFTER_SECONDS)%' diff --git a/Resource/locale/messages.ja.yml b/Resource/locale/messages.ja.yml index 5fa143f..b2e7e04 100644 --- a/Resource/locale/messages.ja.yml +++ b/Resource/locale/messages.ja.yml @@ -1,59 +1,63 @@ admin.setting.shop.shop.customer_two_factor_is_activate_sms: 本会員時の本人認証 admin.setting.shop.shop.customer_two_factor_is_activate_sms_tooltip: 本会員登録時、メール認証に加え携帯電話による本人認証を実施します -admin.setting.shop.shop.customer_two_factor_auth: 2段階認証機能 -admin.setting.shop.shop.customer_two_factor_auth_tooltip: ログイン時、通常(メールアドレス・パスワード)認証に加え、多要素認証プラグインによる2段階認証を実施します。 -admin.setting.shop.shop.customer_two_factor_auth_type: 2段階認証方法 -admin.setting.shop.shop.customer_two_factor_auth_type_tooltip: - -admin.setting.2fa.config.title: 2段階認証設定 -admin.setting.2fa.sms.sub_title : SMS送信設定(Twilio) -admin.setting.2fa.sms.sid : SID -admin.setting.2fa.sms.api_token : APIトークン -admin.setting.2fa.sms.from_phone_number : 送信元電話番号 - -admin.setting.2fa.route.sub_title : 認証ルーティング設定 -admin.setting.2fa.route.include : 重要操作ルーティング -admin.setting.2fa.route.exclude : 除外ルーティング - -admin.customer.2fa.title: 2段階認証設定 -admin.customer.2fa.device_authed: デバイス認証 -admin.customer.2fa.device_authed_phone_number: デバイス認証済み電話番号 -admin.customer.2fa.is_2fa_use: 2段階認証の利用 -admin.customer.2fa.type: 2段階認証方式 - -front.2fa.entry.complete_title: 本人確認を実施してください -front.2fa.entry.complete_message__title: メール認証ありがとうございます。 +admin.setting.shop.shop.customer_two_factor_auth: ログイン時の本人認証 +admin.setting.shop.shop.customer_two_factor_auth_tooltip: ログイン時、通常(メールアドレス・パスワード)認証に加え、多要素認証プラグインによる二段階認証を実施します。 +admin.setting.shop.shop.customer_two_factor_auth_type: 二段階認証方法 +admin.setting.shop.shop.customer_two_factor_auth_type_tooltip: + +admin.setting.2fa.config.title: 二段階認証設定 +admin.setting.2fa.sms.sub_title: SMS送信設定(Twilio) +admin.setting.2fa.sms.sid: SID +admin.setting.2fa.sms.api_token: APIトークン +admin.setting.2fa.sms.from_phone_number: 送信元電話番号 + +admin.setting.2fa.route.sub_title: 認証ルーティング設定 +admin.setting.2fa.route.include: 重要操作ルーティング +admin.setting.2fa.route.exclude: 除外ルーティング + +admin.customer.2fa.title: 二段階認証設定 +admin.customer.2fa.device_authed: 本人認証 +admin.customer.2fa.device_authed_phone_number: 本人認証済み電話番号 +admin.customer.2fa.is_2fa_use: ログイン時の本人認証の利用 +admin.customer.2fa.type: ログイン時の本人認証方式 +admin.customer.2fa.type_option.default: 未設定 + +front.2fa.entry.complete_title: ご本人確認を実施してください +front.2fa.entry.complete_message__title: 仮登録ありがとうございます。 front.2fa.entry.complete_message__activated: | 続いて携帯電話によるご本人様確認をお願いいたします。 ご本人様確認を頂けない場合、当ショップはご利用できません。 -front.2fa.entry.go_to_auth: 本人確認へ +front.2fa.entry.go_to_auth: ご本人確認へ -front.2fa.device_auth.title: 本人確認 +front.2fa.device_auth.title: ご本人確認 front.2fa.device_auth.send.message: | 携帯電話に認証コードを送信します。 - お手持ちの携帯電話番号を入力してください。 + お手持ちの携帯電話番号を入力して「認証コードを送信」をクリックしてください。 front.2fa.device_auth.input.message: | 携帯電話に送信された認証コードを入力してください。 送信されていない場合は「認証コードを再送信」をクリックしてください。 -front.2fa.title: 2段階認証 +front.2fa.title: 二段階認証 front.2fa.sms.send.message: | 携帯電話に認証コードを送信します。 - お手持ちの携帯電話番号を入力してください。 + お手持ちの携帯電話番号を入力して「認証コードを送信」をクリックしてください。 front.2fa.sms.input.message: | 携帯電話に送信された認証コードを入力してください。 - 送信されていない場合は「認証コードを再送信」をクリックしてください。 + 送信されていない場合は、「認証コードを再送信」をクリックしてください。 + +front.2fa.sms.phone.place_holder: 電話番号を入力してください +front.2fa.sms.token.place_holder: 認証コードを入力して下さい -front.2fa.complete_message: 2段階認証の設定が完了しました。 -front.2fa.invalid_message__reinput : 2段階認証の設定に失敗しました。再度入力してください。 -front.2fa.configured_warning : 2段階認証は既に設定されています。 +front.2fa.complete_message: 二段階認証の設定が完了しました。 +front.2fa.invalid_message__reinput: 二段階認証の設定に失敗しました。再度入力してください。 +front.2fa.configured_warning: 二段階認証は既に設定されています。 -front.2fa.type: 2段階認証方式 +front.2fa.type: 二段階認証方式 front.2fa.type_message: | - 2段階認証方式を選択してください。 + 二段階認証方式を選択してください。 front.2fa.sms.send: 認証コードを送信 front.2fa.sms.resend: 認証コードを再送信 front.2fa.auth: 認証 -front.2fa.setting: 設定 -front.2fa.onetime.invalid_message__reinput : 認証に失敗しました。正しい認証コードを入力してください。 -front.2fa.sms.send.failure_message : 認証コードが送信できませんでした。正しい電話番号を入力してください。 +front.2fa.setting: 認証方式を設定 +front.2fa.onetime.invalid_message__reinput: 認証に失敗しました。正しい認証コードを入力してください。 +front.2fa.sms.send.failure_message: 認証コードが送信できませんでした。正しい電話番号を入力してください。 diff --git a/Resource/template/admin/config.twig b/Resource/template/admin/config.twig index e310ba4..2c87445 100644 --- a/Resource/template/admin/config.twig +++ b/Resource/template/admin/config.twig @@ -29,21 +29,27 @@
- +
{{ form_widget(form.api_key) }} {{ form_errors(form.api_key) }}
- +
- {{ form_widget(form.api_secret) }} - {{ form_errors(form.api_secret) }} + {{ form_widget(form.plain_api_secret, { type : 'password'}) }} + {{ form_errors(form.plain_api_secret) }}
- +
{{ form_widget(form.from_phone_number) }} {{ form_errors(form.from_phone_number) }} @@ -67,19 +73,13 @@
- +
{{ form_widget(form.include_routes, { 'attr': { 'rows': 8 }}) }} {{ form_errors(form.include_routes) }}
-
- -
- {{ form_widget(form.exclude_routes, { 'attr': { 'rows': 8 }}) }} - {{ form_errors(form.exclude_routes) }} -
-
@@ -92,7 +92,8 @@
diff --git a/Resource/template/admin/customer_edit.twig b/Resource/template/admin/customer_edit.twig old mode 100644 new mode 100755 index 9713fd0..4d53fe7 --- a/Resource/template/admin/customer_edit.twig +++ b/Resource/template/admin/customer_edit.twig @@ -1,11 +1,11 @@ {# - This file is part of the Coupon plugin +This file is part of EC-CUBE - Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. - http://www.ec-cube.co.jp/ +Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. +http://www.ec-cube.co.jp/ - For the full copyright and license information, please view the LICENSE - file that was distributed with this source code. +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. #}
-
- {{ 'admin.setting.shop.shop.customer_two_factor_is_activate_sms'|trans }} - -
+
+ {{ 'admin.setting.shop.shop.customer_two_factor_is_activate_sms'|trans }} + +
{{ form_widget(form.option_activate_device) }} diff --git a/Resource/template/admin/shop_edit_tfa.twig b/Resource/template/admin/shop_edit_tfa.twig index 94cdb5f..90680dd 100644 --- a/Resource/template/admin/shop_edit_tfa.twig +++ b/Resource/template/admin/shop_edit_tfa.twig @@ -1,14 +1,15 @@ {# - This file is part of the Coupon plugin +This file is part of EC-CUBE - Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. - http://www.ec-cube.co.jp/ +Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. +http://www.ec-cube.co.jp/ - For the full copyright and license information, please view the LICENSE - file that was distributed with this source code. +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. #}